Merge branch 'feat/developer/kmc-convert' into feat/developer/kmc-convert-createSeperateUtil
Some checks are pending
Keyman Build Summary / Summarize build status checks (push) Waiting to run

This commit is contained in:
SabineSIL 2026-05-19 10:08:44 +02:00 • committed by GitHub
commit e1d645d1f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 211 additions and 464 deletions

View file

@ -17,12 +17,6 @@ const SevError = CompilerErrorSeverity.Error | Namespace;
*/
export class ConverterMessages {
static ERROR_InputFilenameIsRequired = SevError | 0x0002;
static Error_InputFilenameIsRequired = () => m(
this.ERROR_InputFilenameIsRequired,
`An input filename is required for keyboard conversion.`
);
static ERROR_FileNotFound = SevError | 0x0003;
static Error_FileNotFound = (o: { inputFilename: string; }) => m(
this.ERROR_FileNotFound,
@ -42,27 +36,21 @@ export class ConverterMessages {
);
static ERROR_UnableToRead = SevError | 0x0006;
static Error_UnableToRead = () => m(
static Error_UnableToRead = (o: { errorText: string; }) => m(
this.ERROR_UnableToRead,
`Input file could not be read.`
);
static ERROR_UnableToParse = SevError | 0x000C;
static Error_UnableToParse = () => m(
this.ERROR_UnableToParse,
`Input data could not be parsed.`
`Input file could not be read. ${def(o.errorText)}`
);
static ERROR_UnsupportedCharactersDetected = SevError | 0x0007;
static Error_UnsupportedCharactersDetected = (o: { inputFilename: string, keymapIndex: string, KeyName: string, output: string; }) => m(
static Error_UnsupportedCharactersDetected = (o: { keymapIndex: string, key: string, KeyName: string, output: string; }) => m(
this.ERROR_UnsupportedCharactersDetected,
`Input file ${def(o.inputFilename)} contains unsupported character '${def(o.output)}' at keyMap index ${def(o.keymapIndex)} on Key ${def(o.KeyName)}`
`Input file contains unsupported character '${def(o.output)}' at keyMap index ${def(o.keymapIndex)} on Keycode ${def(o.key)} (${def(o.KeyName)})`
);
static ERROR_UndefinedActionDetected = SevError | 0x0008;
static Error_UndefinedActionDetected = (o: { inputFilename: string, action: string, KeyName: string, keymapIndex: string; }) => m(
static Error_UndefinedActionDetected = (o: { action: string, KeyName: string, keymapIndex: string; }) => m(
this.ERROR_UndefinedActionDetected,
`${def(o.inputFilename)}: Action id ${def(o.action)} of key ${def(o.KeyName)} in keymapIndex ${def(o.keymapIndex)} is not defined`
`Action id ${def(o.action)} of key ${def(o.KeyName)} in keymapIndex ${def(o.keymapIndex)} is not defined`
);
static ERROR_NoConverterFound = SevError | 0x0009;
@ -83,4 +71,9 @@ export class ConverterMessages {
`Output file for '${def(o.outputFilename)}' could not be written. ${def(o.errorText)}`
);
static ERROR_UnableToParse = SevError | 0x000C;
static Error_UnableToParse = () => m(
this.ERROR_UnableToParse,
`Input data could not be parsed.`
);
}

View file

@ -64,7 +64,7 @@ export class Converter implements KeymanCompiler {
};
if (!inputFilename) {
this.callbacks.reportMessage(ConverterMessages.Error_InputFilenameIsRequired());
throw new Error('Input filename is required');
return null;
}

View file

@ -161,9 +161,9 @@ export class KeylayoutFileReader {
this.boxArray(jsonObj.keyboard); // jsonObj now contains arrays; no single fields
return jsonObj;
}
catch (err) {
this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead());
catch (err: any) {
this.callbacks.reportMessage(ConverterMessages.Error_UnableToRead({ errorText: err }));
return null;
}
}
}
};

View file

@ -22,7 +22,7 @@ export interface ConverterResult extends KeymanCompilerResult {
artifacts: ConverterArtifacts;
};
export interface ConverterToKmnResult extends ConverterResult {
interface ConverterToKmnResult extends ConverterResult {
/*
* Internal in-memory build artifacts from a successful compilation. Caller
* can write these to disk with {@link Converter.write}
@ -111,10 +111,9 @@ export class KeylayoutToKmnConverter {
async run(inputFilename: string, outputFilename?: string): Promise<ConverterToKmnResult> {
if (!inputFilename) {
this.callbacks.reportMessage(ConverterMessages.Error_FileNotFound({ inputFilename }));
throw new Error('Input filename is required');
return null;
}
const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/);
const binaryData = this.callbacks.loadFile(inputFilename);
@ -315,7 +314,6 @@ export class KeylayoutToKmnConverter {
const b1ActionIndex: number = this.getActionIndexFromActionId(jsonObj, actionId);
if (b1ActionIndex < 0) {
this.callbacks.reportMessage(ConverterMessages.Error_UndefinedActionDetected({
inputFilename: jsonObj.keyboard['name'] + ".keylayout",
action: actionId,
KeyName: this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])),
keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index']
@ -484,9 +482,9 @@ export class KeylayoutToKmnConverter {
}
} else {
this.callbacks.reportMessage(ConverterMessages.Error_UnsupportedCharactersDetected({
inputFilename: jsonObj.keyboard['name'] + ".keylayout",
keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'],
output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'],
output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] ?? '',
key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'],
KeyName: this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']))
}));
return null;
@ -1037,7 +1035,7 @@ export class KeylayoutToKmnConverter {
}
/** @internal */
public convertBound = {
public unitTestEndpoints = {
convert: this.convert.bind(this),
};
}

View file

@ -13,10 +13,14 @@ import { ConverterMessages } from '../converter-messages.js';
import KEYMAN_VERSION from "@keymanapp/keyman-version";
import { convertUtil } from '@keymanapp/common-types';
export interface messageCharacter {
interface MessageCharacter {
message: string;
character: string;
};
// Todo-kmc-convert edit interface
/*interface ReviewRulesResult {
warningMessage: string[];
};*/
export class KmnFileWriter {
@ -177,12 +181,24 @@ export class KmnFileWriter {
+ '\"\n';
}
else {
data += warningTextToWrite
+ "+ ["
+ (uniqueDataRules[k].modifierKey + ' ' + uniqueDataRules[k].key).trim()
+ `] > \'`
+ versionOutputCharacter
+ '\'\n';
// surround all output characters with '' (e.g. + [K_A] > 'A')
// but don`t for U+xxxx in control character message (e.g. c Use of a control character + [K_A] > U+0011 )
if (warningTextToWrite.indexOf("control character") === -1) {
data += warningTextToWrite
+ "+ ["
+ (uniqueDataRules[k].modifierKey + ' ' + uniqueDataRules[k].key).trim()
+ `] > \'`
+ versionOutputCharacter
+ '\'\n';
}
else {
data += warningTextToWrite
+ "+ ["
+ (uniqueDataRules[k].modifierKey + ' ' + uniqueDataRules[k].key).trim()
+ `] > `
+ versionOutputCharacter
+ '\n';
}
}
}
}
@ -249,17 +265,28 @@ export class KmnFileWriter {
+ '\"\n';
}
else {
data += warningTextToWrite
+ "dk(A"
+ (String(uniqueDataRules[k].idDeadkey) + ") + ["
+ uniqueDataRules[k].modifierKey).trim()
+ " "
+ uniqueDataRules[k].key + "] > \'"
+ versionOutputCharacter
+ "\'\n";
// surround all output characters with '' (e.g. + [K_A] > 'A')
// but don`t for U+xxxx in control character message (e.g. c Use of a control character + [K_A] > U+0011 )
if (warningTextToWrite.indexOf("control character") === -1) {
data += warningTextToWrite
+ "dk(A"
+ (String(uniqueDataRules[k].idDeadkey) + ") + ["
+ uniqueDataRules[k].modifierKey).trim()
+ " "
+ uniqueDataRules[k].key + "] > \'"
+ versionOutputCharacter
+ "\'\n";
} else {
data += warningTextToWrite
+ "dk(A"
+ (String(uniqueDataRules[k].idDeadkey) + ") + ["
+ uniqueDataRules[k].modifierKey).trim()
+ " "
+ uniqueDataRules[k].key + "] > "
+ versionOutputCharacter
+ "\n";
}
}
}
data += "\n";
}
@ -333,15 +360,31 @@ export class KmnFileWriter {
}
if (!((warnText[2].length > 0) && KeylayoutToKmnConverter.SKIP_COMMENTED_LINES)) {
data += warningTextToWrite + "dk(B"
+ (String(uniqueDataRules[k].idDeadkey)
+ ") + ["
+ uniqueDataRules[k].modifierKey).trim()
+ " "
+ uniqueDataRules[k].key
+ "] > \'"
+ versionOutputCharacter
+ "\'\n";
// surround all output characters with '' (e.g. + [K_A] > 'A')
// but don`t for U+xxxx in control character message (e.g. c Use of a control character + [K_A] > U+0011 )
if (warningTextToWrite.indexOf("control character") === -1) {
data += warningTextToWrite + "dk(B"
+ (String(uniqueDataRules[k].idDeadkey)
+ ") + ["
+ uniqueDataRules[k].modifierKey).trim()
+ " "
+ uniqueDataRules[k].key
+ "] > \'"
+ versionOutputCharacter
+ "\'\n";
} else {
data += warningTextToWrite + "dk(B"
+ (String(uniqueDataRules[k].idDeadkey)
+ ") + ["
+ uniqueDataRules[k].modifierKey).trim()
+ " "
+ uniqueDataRules[k].key
+ "] > "
+ versionOutputCharacter
+ "\n";
}
}
}
@ -362,7 +405,10 @@ export class KmnFileWriter {
* @param index the index of a rule in Rule[]
* @return a string[] containing possible warnings for a rule
*/
public reviewRules(rule: Rule[], index: number): string[] {
private reviewRules(rule: Rule[], index: number): string[] {
/*const result: ReviewRulesResult = {
warningMessage: []
};*/
const keylayoutKmnConverter = new KeylayoutToKmnConverter(this.callbacks, this.options);
const warningText: string[] = Array(3).fill("");
@ -848,6 +894,7 @@ export class KmnFileWriter {
warningText[2] = warningText[2] + extraWarning;
}
}
//result.warningMessage = warningText;
return warningText;
}
@ -859,14 +906,14 @@ export class KmnFileWriter {
* a non-control character will be written as itself ( 'A', '1', '፩', '😎')
* null in case of an empty string or null or undefined input
*/
public writeCharacterOrUnicode(ctr: string, msg: string = ""): messageCharacter {
public writeCharacterOrUnicode(ctr: string, msg: string = ""): MessageCharacter {
if ((ctr === null) || (ctr === undefined) || (ctr.length === 0)) {
return null;
}
let versionOutputCharacter;
const out: messageCharacter = {
const out: MessageCharacter = {
message: msg,
character: ctr
};
@ -880,7 +927,7 @@ export class KmnFileWriter {
m_uni ? parseInt(m_uni[1], 16) : m_hex ? parseInt(m_hex[1], 16) : parseInt(m_dec[1], 10) : KeylayoutToKmnConverter.MAX_CTRL_CHARACTER
);
// for control charactersin 'U+...', '&#x...' or '&#...' format as well as in "" format
// for control characters in 'U+...', '&#x...' or '&#...' format as well as in "" format
if ((ctr_val < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER) || (ctr.charCodeAt(0) < KeylayoutToKmnConverter.MAX_CTRL_CHARACTER)) {
// for control characters in 'U+...', '&#x...' or '&#...' format
@ -908,3 +955,4 @@ export class KmnFileWriter {
return out;
}
}

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated April 15 2025
Generated by S. Schmitt
a test with lots of shiftstates, behaviours and C0, C1, C2 C3 rules
the main testcase containing lots of shiftstates, behaviours and C0, C1, C2 C3 rules
-->
<keyboard group="126" id="-1272" name="Test" maxout="1">

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
tests C0, C1, C2, C3 rules
tests basic C0, C1, C2, C3 rules
-->
<keyboard group="126" id="-1272" name="Test_C0_C1_C2_C3" maxout="1">

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
tests C2 rule
tests C2 single rule
-->
<keyboard group="126" id="-1272" name="Test_C2" maxout="1">

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated April 15 2025

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
tests if duplicate definitions return a warning
Tests if duplicate key definitions return a warning
-->
<keyboard group="126" id="-1272" name="Test_ambiguous_keys" maxout="1">

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
test different kinds of characters
test different kinds of encoding of characters
-->
<keyboard group="126" id="-1272" name="Test_characters" maxout="1">

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
if keymaps have different amount of keys derfined -> should print all ( here 2+4 rules)
if keymaps have different amount of keys defined -> should print all (here 2+4 rules)
-->
<keyboard group="126" id="-1272" name="Test_nr_elements" maxout="1">

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
tests C0, C1, C2, C3 rules
tests C0, C1, C2, C3 rules fur use of different encodings
-->
<keyboard group="126" id="-1272" name="Test_differentEncodings" maxout="1">

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
duplicate rules will not be printed out into the kmn file
tests if duplicate rules will not be printed out into the kmn file
-->
<keyboard group="126" id="-1272" name="Test_duplicate_keys" maxout="1">

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025

View file

@ -1,59 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
tests different order of keys in keymap
tests missing keys in keymap
tests duplicate keys in keymap
-->
<keyboard group="126" id="-1272" name="Test_duplicate_missing_keys" maxout="1">
<layouts>
<layout first="0" last="0" mapSet="138" modifiers="30"/>
</layouts>
<modifierMap id="30" defaultIndex="0">
<keyMapSelect mapIndex="0">
<modifier keys=""/>
</keyMapSelect>
<keyMapSelect mapIndex="1">
<modifier keys="caps"/>
</keyMapSelect>
<keyMapSelect mapIndex="2">
<modifier keys="shift caps"/>
</keyMapSelect>
</modifierMap>
<keyMapSet id="ANSI">
<keyMap index="0">
<key code="0" output="a"/>
<key code="1" output="s"/>
<key code="2" output="d"/>
<key code="3" output="f"/>
</keyMap>
<keyMap index="1">
<key code="0" output="a"/>
<key code="1" output="s"/>
<key code="1" output="s"/>
<key code="1" output="s"/>
<key code="1" output="s"/>
<key code="1" output="s"/>
</keyMap>
<keyMap index="2">
<key code="0" output="a"/>
<key code="1" output="s"/>
<key code="1" output="d"/>
<key code="1" output="f"/>
</keyMap>
</keyMapSet>
<actions>
<action id="A_0">
<when state="none" output=" "/>
</action>
</actions>
<terminators>
<when state="1" output="ˆ"/>
</terminators>
</keyboard>

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
tests maximum key is 49 (K_SPACE), 50 will not be processed
tests if maximum key is 49 (K_SPACE), 50 will not be processed
-->
<keyboard group="126" id="-1272" name="Test_nr_elements" maxout="1">

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated April 15 2025

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025

View file

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated April 15 2025
Generated by S. Schmitt
tests several C2 rules for messages
tests if rules contain an unavailable superior rule (e.g. [ K_EQUAL] > dk(A2) )
If that rule is not used, a dependant rule ( e.g. not dk(A2) + [K_A] > 'Â') would have no effect
-->
<keyboard group="126" id="-1272" name="Test_messages_superior_C2" maxout="1">

View file

@ -6,7 +6,8 @@
Generated by S. Schmitt
tests C3 rules
tests if rules contain an unavailable superior rule (e.g. [ K_EQUAL] > dk(A2) )
If that rule is not used, a dependant rule ( e.g. not dk(A2) + [K_A] > 'Â') would have no effect
-->
<keyboard group="126" id="-1272" name="Test_C3" maxout="1">
<layouts>

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
test how modifiers will be translated into kmn modifieres (includes caps)
test how modifiers will be translated to kmn modifieres (includes caps)
-->
<keyboard group="126" id="-1272" name="Test_modifier" maxout="1">

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
tests how modifiers will be translated into kmn modifieres (with caps)
tests how modifiers will be translated to kmn modifieres (with caps)
this is esentiially the same as Test_modifier.keylayout with every CAPS removed which results in
- skipping NCAPS in these cases

View file

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
more keyMapSelect than KeyMap
tests for Errors if less keyMapSelect(2) than KeyMap(3) are available; also uses 2 keyMapSet
-->
<keyboard group="126" id="-1272" name="Test_DifferentAmountOfMapSelectInKeyMapERROR" maxout="1">

View file

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated April 15 2025
Generated by S. Schmitt
more KeyMap than keyMapSelect
tests for Errors if less keyMapSelect(2) than KeyMap(3) are available
-->
<keyboard group="126" id="-1272" name="Test_DifferentAmountOfMapSelectInKeyMapERROR_1" maxout="1">

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
more keyMapSelect than KeyMap
tests for Errors if more keyMapSelect(3) than KeyMap(2) are available
-->
<keyboard group="126" id="-1272" name="Test_DifferentAmountOfMapSelectInKeyMapERROR" maxout="1">

View file

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
if keymaps have different amount of keys defined -> should print all ( here 2+4 rules)
-->
<keyboard group="126" id="-1272" name="Test_nr_elements" maxout="1">
<layouts>
<layout first="0" last="0" mapSet="138" modifiers="30"/>
</layouts>
<modifierMap id="30" defaultIndex="0">
<keyMapSelect mapIndex="0">
<modifier keys=""/>
</keyMapSelect>
<keyMapSelect mapIndex="1">
<modifier keys="caps"/>
</keyMapSelect>
</modifierMap>
<keyMapSet id="ANSI">
<keyMap index="0">
<key code="0" output="a"/>
<key code="1" output="s"/>
</keyMap>
<keyMap index="1">
<key code="0" output="A"/>
<key code="1" output="S"/>
<key code="2" output="D"/>
<key code="3" output="F"/>
</keyMap>
</keyMapSet>
<actions>
<action id="a0">
<when state="none" output=" "/>
</action>
</actions>
<terminators>
<when state="1" output="ˆ"/>
</terminators>
</keyboard>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025

View file

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/keylayout/dtd/keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
tests C0, C1, C2, C3 rules
tests if there will be an Error when using a non-defined action
-->
<keyboard group="126" id="-1272" name="Test_missingAction" maxout="1">

View file

@ -1,58 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE keyboard SYSTEM "../../../../../resources/standards-data/Keylayout/Keylayout.dtd">
<!--
Data generated August 1st 2025
Generated by S. Schmitt
tests C0, C1, C2, C3 rules
-->
<keyboard group="126" id="-1272" name="Test_unsupportedCharacters" maxout="1">
<layouts>
<layout first="0" last="0" mapSet="138" modifiers="30"/>
</layouts>
<modifierMap id="30" defaultIndex="0">
<keyMapSelect mapIndex="0">
<modifier keys="caps"/>
</keyMapSelect>
<keyMapSelect mapIndex="1">
<modifier keys="anyOption"/>
</keyMapSelect>
</modifierMap>
<keyMapSet id="ANSI">
<keyMap index="0">
<key code="0" output=""/> <!-- C0-> keyman rule part 1 -->
<key code="1" action="a1"/> <!-- C1-> keyman rule part 1 -->
<key code="2" action="a0"/> <!-- C2-> keyman rule part 6 -->
<key code="32" action="a4"/> <!-- C1-> keyman rule part 1 -->
</keyMap>
<keyMap index="1">
<key code="24" action="a3"/> <!-- C2-> keyman rule part 3 -->
<key code="28" action="a2"/> <!-- C2-> keyman rule part 3 -->
<key code="32" action="a1"/> <!-- C1-> keyman rule part 1 --> <!-- C3-> keyman rule part 6 -->
</keyMap>
</keyMapSet>
<actions>
<action id="a0">
<when state="1" output="Â"/> <!-- C3-> keyman rule part 6 -->
</action>
<action id="a1">
<when state="none" output="Q"/> <!-- C1-> keyman rule part 1-->
<when state="3" next="1"/> <!-- C3-> keyman rule part 5 -->
</action>
<action id="a2">
<when state="none" next="3"/> <!-- C3-> keyman rule part 4 -->
</action>
<action id="a3">
<when state="none" next="1"/> <!-- C2-> keyman rule part 3 -->
</action>
<action id="a4">
<when state="none" output="U"/> <!-- C1-> keyman rule part 1 -->
</action>
</actions>
<terminators>
<when state="1" output="ˆ"/>
</terminators>
</keyboard>

View file

@ -1,89 +0,0 @@
<!--
* Keyman is copyright (C) SIL Global. MIT License.
*
* Created by S. Schmitt on 2025-07-14
*
* This DTD describes a technical preview of Keylayout Data
*
* Unless otherwise specified we used TN 2056:
* https://developer.apple.com/library/archive/technotes/tn2056/_index.html#//apple_ref/doc/uid/DTS10003085-CH1-SUBSECTION7
*
* kmc-convert does not need and therefore does not process the following attributes:
* group, id, maxout,
* first, last, mapSet, modifiers,
* defaultIndex,
* baseMapSet, baseIndex,
* through, multiplier
* kmc-convert does not need and therefore does not process the following elements:
* terminators
* kmc-convert does not need and therefore does not process 'anonymous actions'
* -->
<!-- Overall structure -->
<!-- from TN 2056:
<!ELEMENT keyboard (layouts+, modifierMap+, keyMapSet+, actions*, terminators*)>
kmc-convert uses instead: -->
<!ELEMENT keyboard layouts>
<!ELEMENT keyboard modifierMap+>
<!ELEMENT keyboard keyMapSet+>
<!ELEMENT keyboard actions*>
<!ELEMENT keyboard terminators*>
<!ATTLIST keyboard group NMTOKEN #REQUIRED >
<!ATTLIST keyboard id NMTOKEN #REQUIRED >
<!ATTLIST keyboard name CDATA #REQUIRED >
<!ATTLIST keyboard maxout NMTOKEN #IMPLIED >
<!-- Hardware layout elements -->
<!ELEMENT layouts (layout+) >
<!ELEMENT layout EMPTY >
<!ATTLIST layout first NMTOKEN #REQUIRED >
<!ATTLIST layout last NMTOKEN #REQUIRED >
<!ATTLIST layout mapSet IDREF #REQUIRED >
<!ATTLIST layout modifiers IDREF #REQUIRED >
<!-- Modifier descriptions -->
<!ELEMENT modifierMap (keyMapSelect+) >
<!ATTLIST modifierMap id ID #REQUIRED >
<!ATTLIST modifierMap defaultIndex NMTOKEN #REQUIRED >
<!ELEMENT keyMapSelect (modifier+) >
<!ATTLIST keyMapSelect mapIndex NMTOKEN #REQUIRED >
<!ELEMENT modifier EMPTY >
<!ATTLIST modifier keys CDATA #REQUIRED >
<!-- Keyboard mapping most keyboards use ANSI only but some use JIS also -->
<!ELEMENT keyMapSet (keyMap+) >
<!ATTLIST keyMapSet id ID #REQUIRED >
<!ELEMENT keyMap (key+) >
<!ATTLIST keyMap index NMTOKEN #REQUIRED >
<!ATTLIST keyMap baseMapSet IDREF #IMPLIED >
<!ATTLIST keyMap baseIndex NMTOKEN #IMPLIED >
<!ELEMENT key (action*) >
<!ATTLIST key code NMTOKEN #REQUIRED >
<!-- from TN 2056:
<!ATTLIST key output CDATA #IMPLIED >
<!ATTLIST key action IDREF #IMPLIED >
since output or action needs to be present kmc-convert uses instead: -->
<!ATTLIST key (action #REQUIRED output #IMPLIED | output #REQUIRED action #IMPLIED)>
<!-- Actions (state records) -->
<!ELEMENT actions (action+) >
<!ELEMENT action (when+) >
<!ATTLIST action id ID #IMPLIED >
<!ELEMENT when EMPTY >
<!ATTLIST when state NMTOKEN #REQUIRED >
<!ATTLIST when through NMTOKEN #IMPLIED >
<!ATTLIST when output CDATA #IMPLIED >
<!ATTLIST when multiplier NMTOKEN #IMPLIED >
<!ATTLIST when next NMTOKEN #IMPLIED >
<!-- Terminators -->
<!-- kmc-convert does not use terminators -->
<!ELEMENT terminators (when+)>

View file

@ -3,7 +3,7 @@
*
* Created by S. Schmitt on 2025-05-12
*
* Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter
* Tests for KeylayoutFileReader
*
*/
@ -27,23 +27,23 @@ describe('KeylayoutFileReader', function () {
assert.isNotEmpty(result);
});
it('read() should return empty array on empty input', async function () {
it('read() should return null on empty input', async function () {
const result = sutR.read(compilerTestCallbacks.loadFile(""));
assert.isNull(result);
});
it('read() should return empty array on space as input', async function () {
it('read() should return null on space as input', async function () {
const result = sutR.read(compilerTestCallbacks.loadFile(" "));
assert.isNull(result);
});
it('read() should return empty array on unavailable file name', async function () {
it('read() should return null on unavailable file name', async function () {
const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout');
const result = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable));
assert.isNull(result);
});
it('read() should return empty array on typo in path', async function () {
it('read() should return null on typo in path', async function () {
const result = sutR.read(compilerTestCallbacks.loadFile(makePathToFixture('../data|Test.keylayout')));
assert.isNull(result);
});

View file

@ -3,7 +3,7 @@
*
* Created by S. Schmitt on 2025-05-12
*
* Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter
* Tests for KeylayoutToKmnConverter
*
*/
import 'mocha';
@ -60,40 +60,30 @@ describe('KeylayoutToKmnConverter', function () {
describe('RunSpecialTestFiles', function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
[
[makePathToFixture('../data/Test_mixedEncodings.keylayout')],
[makePathToFixture('../data/Test_invalidInput_C0.keylayout')],
[makePathToFixture('../data/Test_invalidInput_C1.keylayout')],
[makePathToFixture('../data/Test_invalidInput_C2.keylayout')],
[makePathToFixture('../data/Test_invalidInput_C3.keylayout')],
[makePathToFixture('../data/Test_Character_Codepoint_C0.keylayout')],
[makePathToFixture('../data/Test_Character_Codepoint_C2.keylayout')],
[makePathToFixture('../data/Test_Character_Codepoint_C3.keylayout')],
[makePathToFixture('../data/Test_C0.keylayout')],
[makePathToFixture('../data/Test_C1.keylayout')],
[makePathToFixture('../data/Test_C2.keylayout')],
[makePathToFixture('../data/Test_C2_several.keylayout')],
[makePathToFixture('../data/Test_C3.keylayout')],
[makePathToFixture('../data/Test_C3_several.keylayout')],
[makePathToFixture('../data/Test_C0_C1_C2_C3.keylayout')],
[makePathToFixture('../data/Test_maxKeyCode.keylayout')],
[makePathToFixture('../data/Test_messages.keylayout')],
[makePathToFixture('../data/Test_messages_controlCharacter.keylayout')],
[makePathToFixture('../data/Test_messages_superior_C2.keylayout')],
[makePathToFixture('../data/Test_messages_superior_C3.keylayout')],
[makePathToFixture('../data/Test_duplicate_missing_keycode.keylayout')],
[makePathToFixture('../data/Test_modifier.keylayout')],
[makePathToFixture('../data/Test_modifierNoCaps.keylayout')],
[makePathToFixture('../data/Test_differentAmountOfKeysInBehaviours.keylayout')],
[makePathToFixture('../data/Test_duplicate_missing_keys.keylayout')],
[makePathToFixture('../data/Test_duplicate_keys.keylayout')],
[makePathToFixture('../data/Test_ambiguous_keys.keylayout')],
[makePathToFixture('../data/Test_nr_elements.keylayout')],
[makePathToFixture('../data/Test.keylayout')],
[makePathToFixture('../data/Test_differentEncodings.keylayout')],
[makePathToFixture('../data/Test_ExtraWarning.keylayout')],
['../data/Test_C0.keylayout'],
['../data/Test_C1.keylayout'],
['../data/Test_C2.keylayout'],
['../data/Test_C2_several.keylayout'],
['../data/Test_C3.keylayout'],
['../data/Test_C3_several.keylayout'],
['../data/Test_C0_C1_C2_C3.keylayout'],
['../data/Test_maxKeyCode.keylayout'],
['../data/Test_messages.keylayout'],
['../data/Test_messages_controlCharacter.keylayout'],
['../data/Test_messages_superior_C2.keylayout'],
['../data/Test_messages_superior_C3.keylayout'],
['../data/Test_duplicate_missing_keycode.keylayout'],
['../data/Test_modifier.keylayout'],
['../data/Test_modifierNoCaps.keylayout'],
['../data/Test_differentAmountOfKeysInBehaviours.keylayout'],
['../data/Test_duplicate_keys.keylayout'],
['../data/Test_ambiguous_keys.keylayout'],
['../data/Test.keylayout'],
['../data/Test_differentEncodings.keylayout'],
['../data/Test_ExtraWarning.keylayout'],
].forEach(function (files) {
it(files + " should give no errors ", async function () {
sut.run(files[0]);
sut.run(makePathToFixture(files[0]));
assert.isTrue(compilerTestCallbacks.messages.length === 0);
});
});
@ -102,44 +92,34 @@ describe('KeylayoutToKmnConverter', function () {
describe('RunTestFiles resulting in errors ', function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
[
[makePathToFixture('../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout')],
[makePathToFixture('../data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout')],
[makePathToFixture('../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout')],
[makePathToFixture('../data/Test_MissingkeyERROR.keylayout')],
[makePathToFixture('../data/Test_MissingkeyMapERROR.keylayout')],
[makePathToFixture('../data/Test_MissingLayoutsERROR.keylayout')],
[makePathToFixture('../data/Test_MissingmodifierMapERROR.keylayout')],
[makePathToFixture('../data/Test_MissingkeyMapSetERROR.keylayout')],
[makePathToFixture('../data/Test_MissingActionsERROR.keylayout')],
[makePathToFixture('../data/Test_MissingTerminatorsERROR.keylayout')],
[makePathToFixture('../data/Test_MissingAllERROR.keylayout')],
['../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout'],
['../data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout'],
['../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout'],
['../data/Test_MissingkeyERROR.keylayout'],
['../data/Test_MissingkeyMapERROR.keylayout'],
['../data/Test_MissingLayoutsERROR.keylayout'],
['../data/Test_MissingmodifierMapERROR.keylayout'],
['../data/Test_MissingkeyMapSetERROR.keylayout'],
['../data/Test_MissingActionsERROR.keylayout'],
['../data/Test_MissingTerminatorsERROR.keylayout'],
['../data/Test_MissingAllERROR.keylayout'],
['../data/Test_characters.keylayout'],
].forEach(function (files) {
it(files + " should give an error ", async function () {
sut.run(files[0]);
sut.run(makePathToFixture(files[0]));
assert.isTrue(compilerTestCallbacks.messages.length > 0);
});
});
});
describe('RunSpecialTestFiles - create Error: unsupported characters', function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
[
[makePathToFixture('../data/Test_characters.keylayout')],
].forEach(function (files) {
it(files + " should give Error: unsupported characters ", async function () {
sut.run(files[0]);
assert.isTrue(compilerTestCallbacks.messages.length === 1);
});
});
});
describe('RunSpecialTestFiles - create Error: undefined action', function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
[
[makePathToFixture('../data/Test_undefinedAction.keylayout')],
['../data/Test_undefinedAction.keylayout'],
].forEach(function (files) {
it(files + " should give Error: undefined action detected", async function () {
sut.run(files[0]);
sut.run(makePathToFixture(files[0]));
assert.isTrue(compilerTestCallbacks.messages.length === 1);
assert.equal(compilerTestCallbacks.messages[0].code, 5292040);
});
@ -149,34 +129,13 @@ describe('KeylayoutToKmnConverter', function () {
describe('run() ', function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
it('run() should throw on null input file name and null output file name', async function () {
// note, could use 'chai as promised' library to make this more fluent:
const result = sut.run(null, null);
assert.isNotNull(result);
assert.equal(compilerTestCallbacks.messages.length, 1);
assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null }));
});
it('run() should throw on null input file name and empty output file name', async function () {
const result = sut.run(null, '');
assert.isNotNull(result);
assert.equal(compilerTestCallbacks.messages.length, 1);
assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null }));
});
it('run() should throw on null input file name and unknown output file name', async function () {
const result = sut.run(null, 'X');
assert.isNotNull(result);
assert.equal(compilerTestCallbacks.messages.length, 1);
assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_FileNotFound({ inputFilename: null }));
});
it('run() should throw on unavailable input file name and null output file name', async function () {
const inputFilename = makePathToFixture('../data/Unavailable.keylayout');
const result = sut.run(inputFilename, null);
assert.isNotNull(result);
assert.equal(compilerTestCallbacks.messages.length, 2);
assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead());
//assert.deepEqual(compilerTestCallbacks.messages[0], ConverterMessages.Error_UnableToRead());
assert.isTrue(compilerTestCallbacks.hasMessage(ConverterMessages.ERROR_UnableToRead));
assert.equal(compilerTestCallbacks.messages[1].code, 5292037);
});
});
@ -186,15 +145,13 @@ describe('KeylayoutToKmnConverter', function () {
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
const infile = '../data/Test.keylayout';
[
[makePathToFixture('../data/Test.kmn')],
[makePathToFixture('')],
[],
[null],
[makePathToFixture('../data/test_OtherOutputName.kmn')],
[makePathToFixture('../data/OutputXName.bb')],
['../data/Test.kmn'],
[''],
['../data/test_OtherOutputName.kmn'],
['../data/OutputXName.bb'],
].forEach(function (files) {
it(infile + " should run ", async function () {
await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), files[0]));
await NodeAssert.doesNotReject(async () => sut.run(makePathToFixture(infile), makePathToFixture(files[0])));
assert.equal(compilerTestCallbacks.messages.length, 0);
});
});
@ -207,32 +164,32 @@ describe('KeylayoutToKmnConverter', function () {
// ProcessedData from usable file
const inputFilename = makePathToFixture('../data/Test.keylayout');
const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
const converted = sut.unitTestEndpoints.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
// ProcessedData from unavailable file
const inputFilenameUnavailable = makePathToFixture('../data/X.keylayout');
const readUnavailable = sutR.read(compilerTestCallbacks.loadFile(inputFilenameUnavailable));
const convertedUnavailable = sut.convertBound.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn'));
const convertedUnavailable = sut.unitTestEndpoints.convert(readUnavailable, inputFilenameUnavailable.replace(/\.keylayout$/, '.kmn'));
// ProcessedData from empty file
const inputFilenameEmpty = makePathToFixture('');
const readEmpty = sutR.read(compilerTestCallbacks.loadFile(inputFilenameEmpty));
const convertedEmpty = sut.convertBound.convert(readEmpty, inputFilenameEmpty);
const convertedEmpty = sut.unitTestEndpoints.convert(readEmpty, inputFilenameEmpty);
it('should return converted array on correct input', async function () {
assert.isTrue(converted.rules.length !== 0);
});
it('should return empty on empty name as input', async function () {
it('should return null on empty name as input', async function () {
assert.isNull(convertedUnavailable);
});
it('should return empty on empty input', async function () {
it('should return null on empty input', async function () {
assert.isNull(convertedEmpty);
});
it('should return empty array of rules on null input', async function () {
const convertedRule = sut.convertBound.convert(null, 'ABC.kmn');
it('should return null of rules on null input', async function () {
const convertedRule = sut.unitTestEndpoints.convert(null, 'ABC.kmn');
assert.isNull(convertedRule);
});
});
@ -242,7 +199,6 @@ describe('KeylayoutToKmnConverter', function () {
[
[' ', true, 'NCAPS'],
[' ', false, ''],
['NCAPS', true, 'NCAPS'],
['NCAPS', false, ''],
['caps', true, 'CAPS'],
@ -346,7 +302,6 @@ describe('KeylayoutToKmnConverter', function () {
[[['CaPs', 'xxx'], ['yyy']], true],
[[['Caps?', 'xxx'], ['yyy']], false],
[[['zzz', 'xxx'], ['Caps?']], false],
[[['caps?', 'xxx'], ['yyy']], false],
[[['zzz', 'xxx'], ['yyy']], false],
[[['shift', 'xxx'], ['caps']], true],
[[['shift', 'caps'], ['yyy']], true],
@ -369,7 +324,7 @@ describe('KeylayoutToKmnConverter', function () {
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
const inputFilename = makePathToFixture('../data/Test.keylayout');
const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
const converted = sut.unitTestEndpoints.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
[
[[{ key: '0', behavior: 0 }], [['', 'shift? caps? ']]],
[[{ key: '0', behavior: 2 }], [['shift? leftShift caps? ', 'anyShift caps?', 'shift leftShift caps ', 'shift? rightShift caps? ']]],
@ -384,7 +339,7 @@ describe('KeylayoutToKmnConverter', function () {
it((values[1] !== null) ?
("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + JSON.stringify(values[1]) + "'" :
("getModifierArrayFromKeyModifierArray('" + JSON.stringify(values[0]) + "')").padEnd(68, " ") + " should return '" + "null" + "'", async function () {
const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as unknown as KeylayoutFileData[]);
const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as unknown as KeylayoutFileData[]);
assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1]));
});
});
@ -656,7 +611,7 @@ describe('KeylayoutToKmnConverter', function () {
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
const inputFilename = makePathToFixture('../data/Test.keylayout');
const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
const converted = sut.unitTestEndpoints.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
[
['A_1', 'A', true,
[{ "outchar": "A", "actionId": "A_1", "behavior": "1", "key": "K_A", "modifier": "CAPS" },
@ -845,7 +800,7 @@ describe('KeylayoutToKmnConverter', function () {
it('data of \'' + values[0] + "' passed into createRuleData() " + 'should create an array of rules', async function () {
const inputFilename = makePathToFixture(values[0][0]);
const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
const processedData = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
const processedData = sut.unitTestEndpoints.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
assert.deepEqual(processedData.rules[0], values[1][0]);
});
});

View file

@ -3,7 +3,7 @@
*
* Created by S. Schmitt on 2025-05-12
*
* Tests for KeylayoutToKmnConverter, KeylayoutFileReader, KmnFileWriter
* Tests for KmnFileWriter
*
*/
@ -26,7 +26,7 @@ describe('KmnFileWriter', function () {
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
const converted = sut.unitTestEndpoints.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
it('writeDataRules() should return true (no error) if written', async function () {
const result = sutW.writeDataRules(converted);
@ -41,7 +41,7 @@ describe('KmnFileWriter', function () {
const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
const inputFilename = makePathToFixture('../data/Test.keylayout');
const read = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
const converted = sut.convertBound.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
const converted = sut.unitTestEndpoints.convert(read, inputFilename.replace(/\.keylayout$/, '.kmn'));
const outExpectedFirst: string =
"c ..................................................................................................................\n"
@ -112,7 +112,7 @@ describe('KmnFileWriter', function () {
].forEach(function (values: (string[] | Rule[])[], index: number) {
it(('rule " ' + (values[0][0] as Rule).ruleType as string + ' "') + 'should create "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () {
const result: string[] = sutW.reviewRules(values[0] as Rule[], 0);
const result: string[] = sutW.unitTestEndpoints.reviewRules(values[0] as Rule[], 0);
assert.equal(result[0], values[1][0]);
assert.equal(result[1], values[2][0]);
assert.equal(result[2], values[3][0]);
@ -277,7 +277,7 @@ describe('KmnFileWriter', function () {
].forEach(function (values: (string[] | Rule[])[], index: number) {
it('rule ' + (values[0][0] as Rule).ruleType as string + ' should create " ' + ' "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () {
const result: string[] = sutW.reviewRules(values[0] as Rule[], 1);
const result: string[] = sutW.unitTestEndpoints.reviewRules(values[0] as Rule[], 1);
assert.equal(result[0], values[1][0]);
assert.equal(result[1], values[2][0]);
assert.equal(result[2], values[3][0]);
@ -295,9 +295,9 @@ describe('KmnFileWriter', function () {
[''],
[''],
["c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) ambiguous rule: earlier: [RALT K_B] > 'X' here: PLEASE CHECK THE FOLLOWING RULE AS IT WILL NOT BE WRITTEN ! "]],
].forEach(function (values: (string[] | Rule[])[], index: number) {
it(('rule ' + (values[0][0]as Rule).ruleType as string + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () {
const result: string[] = sutW.reviewRules(values[0]as Rule[], 2);
].forEach(function (values: (string[] | Rule[])[], index: number) {
it(('rule ' + (values[0][0] as Rule).ruleType as string + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () {
const result: string[] = sutW.unitTestEndpoints.reviewRules(values[0] as Rule[], 2);
assert.equal(result[0], values[1][0]);
assert.equal(result[1], values[2][0]);
assert.equal(result[2], values[3][0]);