diff --git a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts
index 5da06e96ba..57760aae63 100644
--- a/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts
+++ b/developer/src/common/web/utils/src/types/keylayout/keylayout-xml.ts
@@ -158,7 +158,9 @@ export interface KL_When {
* to define which output or next is followed by a state
*/
state?: string;
+ through?: string;
output?: string;
+ multiplier?: string;
next?: string;
};
diff --git a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts
index 3d6fb711a9..26ac23a3a1 100644
--- a/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts
+++ b/developer/src/kmc-convert/src/keylayout-to-kmn/keylayout-file-reader.ts
@@ -11,6 +11,7 @@ import { CompilerCallbacks, DeveloperUtilsMessages, Keylayout, KeymanXMLReader }
import { util, SchemaValidators } from '@keymanapp/common-types';
import { ConverterMessages } from '../converter-messages.js';
import boxXmlArray = util.boxXmlArray;
+import { KL_KeyMapSelect,KL_KeyMap } from "../../../common/web/utils/src/types/keylayout/keylayout-xml.js";
export class KeylayoutFileReader {
@@ -23,10 +24,10 @@ export class KeylayoutFileReader {
* @param keyMapSelect the keyMapSelect element to find in keyMapSet
* @return true if the keyMapSet element is found, false if not
*/
- public findMapIndexinKeymap(jsonObj: any, keyMapSelect: any): boolean {
+ public findMapIndexinKeymap(jsonObj: Keylayout.KeylayoutXMLSourceFile, keyMapSelect: KL_KeyMapSelect): boolean {
for (const keyMapSet of jsonObj.keyboard.keyMapSet) {
for (const keyMap of keyMapSet.keyMap) {
- if (keyMap['index'] === keyMapSelect) {
+ if (keyMap['index'] === keyMapSelect.mapIndex) {
return true;
}
}
@@ -40,10 +41,10 @@ export class KeylayoutFileReader {
* @param keyMap the keyMap element to find in modifierMap
* @return true if the keyMap element is found, false if not
*/
- public findIndexinKeymapSelect(jsonObj: any, keyMap: any): boolean {
+ public findIndexinKeymapSelect(jsonObj: Keylayout.KeylayoutXMLSourceFile, keyMap: KL_KeyMap): boolean {
for (const modifierMap of jsonObj.keyboard.modifierMap) {
for (const keyMapSelect of modifierMap.keyMapSelect) {
- if (keyMapSelect['mapIndex'] === keyMap) {
+ if (keyMapSelect['mapIndex'] === keyMap.index) {
return true;
}
}
@@ -58,19 +59,19 @@ export class KeylayoutFileReader {
* @param jsonObj the read keylayout data to be checked
* @return true if all keyMapSelect elements have a corresponding keyMap element, false if not
*/
- public checkForCorrespondingElements(jsonObj: any): boolean {
+ public checkForCorrespondingElements(jsonObj: Keylayout.KeylayoutXMLSourceFile): boolean {
let available = true;
// check if all keyMapSelect elements have a corresponding keyMap element in the .keylayout file
for (const modifierMap of jsonObj.keyboard.modifierMap) {
for (const keyMapSelect of modifierMap.keyMapSelect) {
- available = available && this.findMapIndexinKeymap(jsonObj, keyMapSelect['mapIndex']);
+ available = available && this.findMapIndexinKeymap(jsonObj, keyMapSelect);
}
}
// check if all keyMap elements have a corresponding keyMapSelect element in the .keylayout file
for (const keyMapSet of jsonObj.keyboard.keyMapSet) {
for (const keyMap of keyMapSet.keyMap) {
- available = available && this.findIndexinKeymapSelect(jsonObj, keyMap['index']);
+ available = available && this.findIndexinKeymapSelect(jsonObj, keyMap);
}
}
return available;
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 074c76be37..9db2deb84e 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
@@ -48,7 +48,7 @@ export interface KeylayoutFileData {
actionId?: string;
keyCode?: string;
key?: string;
- behavior?: string;
+ behavior: string;
modifier?: string;
outchar?: string;
};
@@ -124,7 +124,7 @@ export class KeylayoutToKmnConverter {
return null;
}
try {
- if (!KeylayoutReader.validate(jsonO,inputFilename)) {
+ if (!KeylayoutReader.validate(jsonO, inputFilename)) {
return null;
}
} catch (e) {
@@ -150,7 +150,7 @@ export class KeylayoutToKmnConverter {
* @param jsonObj containing filename, behaviorand rules of a json object
* @return an ProcessedData containing all data ready to print out
*/
- private convert(jsonObj: any, inputfilename: string, outputFilename?: string): ProcessedData {
+ private convert(jsonObj: Keylayout.KeylayoutXMLSourceFile, inputfilename: string, outputFilename?: string): ProcessedData {
// modifiers for each behavior
const modifierBehavior: string[][] = [];
@@ -196,7 +196,7 @@ export class KeylayoutToKmnConverter {
* @param jsonObj: json Object containing all data read from a keylayout file
* @return an object containing the name of the input file, an array of behaviors and a populated array of Rules[]
*/
- public createRuleData(dataUkelele: ProcessedData, jsonObj: any): ProcessedData {
+ public createRuleData(dataUkelele: ProcessedData, jsonObj: Keylayout.KeylayoutXMLSourceFile): ProcessedData {
const rules: Rule[] = [];
let dkCounterC3: number = 0;
@@ -260,7 +260,7 @@ export class KeylayoutToKmnConverter {
}
else if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] !== undefined) {
- actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'];
+ actionId = jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] ?? "";
// ...............................................................................................................................
// case C1: action + state none + output .........................................................................................
// C1 see: https://docs.google.com/document/d/12J3NGO6RxIthCpZDTR8FYSRjiMgXJDLwPY2z9xqKzJ0/edit?tab=t.0#heading=h.g7jwx3lx0ydd ...
@@ -317,7 +317,7 @@ export class KeylayoutToKmnConverter {
this.callbacks.reportMessage(ConverterMessages.Error_UndefinedActionDetected({
inputFilename: jsonObj.keyboard['name'] + ".keylayout",
action: actionId,
- KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']),
+ KeyName: this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])),
keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index']
}));
return null;
@@ -325,13 +325,14 @@ export class KeylayoutToKmnConverter {
// with actionId from above loop all 'action' and search for a state(none)-next-pair ............................................................................................................
// e.g. in Block 5: find for action id a18 ......................................................................................................................
- for (let l = 0; l < jsonObj.keyboard.actions.action[b1ActionIndex].when.length; l++) {
- if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'] === "none") // find "none"
- && (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'] !== undefined)) { // find "next"
+ if (jsonObj.keyboard.actions?.action?.[b1ActionIndex]?.when) {
+ for (const when of jsonObj.keyboard.actions.action[b1ActionIndex].when) {
+ if ((when['state'] === "none") // find "none"
+ && (when['next'] !== undefined)) { // find "next"
// Data of Block Nr 5 .....................................................................................................................................................................
// of this state(none)-next-pair get value of next (next="1") .............................................................................................................................
- /* eg: 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'];
+ /* eg: 1 */ const b5ValueNext: string = when['next'];
// ........................................................................................................................................................................................
@@ -339,7 +340,7 @@ export class KeylayoutToKmnConverter {
// with present actionId (a18) find all keycode-behavior-pairs that use this action (a18) => (keymapIndex 0/keycode 24 and keymapIndex 3/keycode 24) ....................................
// from these create an array of modifier combinations e.g. [['','caps?'], ['Caps']] .....................................................................................................
/* eg: [['24', 0], ['24', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId);
- /* e.g. [['','caps?'], ['Caps']]*/ const b4DeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj);
+ /* e.g. [['','caps?'], ['Caps']]*/ const b4DeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj);
// ........................................................................................................................................................................................
@@ -353,14 +354,14 @@ export class KeylayoutToKmnConverter {
// create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] ......................................................................
/* eg: ['0','K_A','a9','0','â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj);
/* eg: ['K_A','a9','0','NCAPS','â']*/ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused);
- // .......................................................................................................................................................................................
+ // .......................................................................................................................................................................................
- for (let n1 = 0; n1 < b4DeadkeyModifierObj.length; n1++) {
- for (let n2 = 0; n2 < b4DeadkeyModifierObj[n1].length; n2++) {
- for (let n3 = 0; n3 < b4DeadkeyObj.length; n3++) {
- for (let n4 = 0; n4 < b1ModifierKeyObj.length; n4++) {
+ for (let n1 = 0; n1 < b4DeadkeyModifierObj.length; n1++) {
+ for (let n2 = 0; n2 < b4DeadkeyModifierObj[n1].length; n2++) {
+ for (let n3 = 0; n3 < b4DeadkeyObj.length; n3++) {
+ for (let n4 = 0; n4 < b1ModifierKeyObj.length; n4++) {
- ruleObj = new Rule(
+ ruleObj = new Rule(
/* ruleType */ "C2",
/* modifierPrevDeadkey*/ "",
@@ -376,11 +377,12 @@ export class KeylayoutToKmnConverter {
/* modifierKey*/ b1ModifierKeyObj[n4].modifier,
/* key */ b1ModifierKeyObj[n4].key,
/* output */ new TextEncoder().encode(b1ModifierKeyObj[n4].outchar),
- );
- if ((b1ModifierKeyObj[n4].outchar !== undefined)
- && (b1ModifierKeyObj[n4].outchar !== "undefined")
- && (b1ModifierKeyObj[n4].outchar !== "")) {
- rules.push(ruleObj);
+ );
+ if ((b1ModifierKeyObj[n4].outchar !== undefined)
+ && (b1ModifierKeyObj[n4].outchar !== "undefined")
+ && (b1ModifierKeyObj[n4].outchar !== "")) {
+ rules.push(ruleObj);
+ }
}
}
}
@@ -416,7 +418,7 @@ export class KeylayoutToKmnConverter {
// with present actionId (a16) find all keycode-behavior-pairs that use this action (a16) => (keymapIndex 3/keycode 32) ....................................................................
// from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] .....................................................................................................
/* e.g. [['32', 3]] */ const b4DeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, actionId);
- /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4DeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj);
+ /* e.g. [ [ 'anyOption', 'Caps' ] ]*/ const b4DeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b4DeadkeyObj);
// ...........................................................................................................................................................................................
// Data of Block Nr 3 ........................................................................................................................................................................
@@ -428,7 +430,7 @@ export class KeylayoutToKmnConverter {
// with present actionId (a17) find all key names and behaviors that use this action (a17) => (keymapIndex 3/keycode 28) ....................................................................
// from these create an array of modifier combinations e.g. [ [ 'anyOption', 'Caps' ] ] .....................................................................................................
/* eg: index=3 */ const b2PrevDeadkeyObj: KeylayoutFileData[] = this.getKeyModifierArrayFromActionID(jsonObj, b3ActionId);
- /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2PrevDeadkeyModifierObj: string[] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b2PrevDeadkeyObj);
+ /* e.g. [ [ 'anyOption', 'Caps' ] ] */ const b2PrevDeadkeyModifierObj: string[][] = this.getModifierArrayFromKeyModifierArray(dataUkelele.modifiers, b2PrevDeadkeyObj);
// ...........................................................................................................................................................................................
// Data of Block Nr 6 ........................................................................................................................................................................
// create an array[action id,state,output] from all state-output-pairs that use state = b5ValueNext (e.g. use 1 in ) .........................................
@@ -486,7 +488,7 @@ export class KeylayoutToKmnConverter {
keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'],
output: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'],
key: jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'],
- KeyName: this.mapUkeleleKeycodeToVK(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])
+ KeyName: this.mapUkeleleKeycodeToVK(Number(jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['code']))
}));
return null;
}
@@ -773,7 +775,7 @@ export class KeylayoutToKmnConverter {
];
if (!(pos >= 0 && pos <= 0x31) || (pos === null) || (pos === undefined)) {
- return "";
+ return "" as string;
} else {
return vk[pos];
}
@@ -781,11 +783,14 @@ export class KeylayoutToKmnConverter {
/**
* @brief member function to return an index for a given actionID
- * @param data :any - an object containing all data read from a .keylayout file
+ * @param data an object containing all data read from a .keylayout file
* @param search :string - value 'id' to be found
* @return a number specifying the index of an actionId
*/
- public getActionIndexFromActionId(data: any, search: string): number {
+ public getActionIndexFromActionId(data: Keylayout.KeylayoutXMLSourceFile, search: string): number {
+ if (!data.keyboard?.actions?.action) {
+ return -1;
+ }
for (let i = 0; i < data.keyboard.actions.action.length; i++) {
if (data.keyboard.actions.action[i]['id'] === search) {
return i;
@@ -796,53 +801,60 @@ export class KeylayoutToKmnConverter {
/**
* @brief member function to find the actionID of a certain state-next pair
- * @param data :any an object containing all data read from a .keylayout file
+ * @param data an object containing all data read from a .keylayout file
* @param search :string value 'next' to be found
* @return a string containing the actionId of a certain state(none)-next pair
*/
- public getActionIdFromActionNext(data: any, search: string): string {
- if (search !== "none") {
- for (let i = 0; i < data.keyboard.actions.action.length; i++) {
- for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) {
- if (data.keyboard.actions.action[i].when[j]['next'] === search) {
- return data.keyboard.actions.action[i]['id'];
+ public getActionIdFromActionNext(data: Keylayout.KeylayoutXMLSourceFile, search: string): string {
+ if (search !== "none" && data.keyboard?.actions?.action) {
+ for (const action of data.keyboard.actions.action) {
+ if (action.when) {
+ for (const when of action.when) {
+ if (when['next'] === search) {
+ return action['id'] as string;
+ }
}
}
}
}
- return "";
+ return "" as string;
}
/**
* @brief member function to create an array of (modifier) behaviors for a given keycode in [{keycode,modifier}]
- * @param data : any - an object containing all data read from a .keylayout file
+ * @param data an object containing all data read from a .keylayout file
* @param search : KeylayoutFileData[] - an array[{keycode,modifier}] to be found
* @return a string[] containing modifiers
*/
- public getModifierArrayFromKeyModifierArray(data: any, search: KeylayoutFileData[]): string[] {
- const returnString1D: string[] = [];
+ public getModifierArrayFromKeyModifierArray(data: ProcessedData["modifiers"], search: KeylayoutFileData[]): string[][] | [null] {
+ const returnString1D: string[][] = [];
for (let i = 0; i < search.length; i++) {
- returnString1D.push(data[search[i].behavior]);
+ if (search[i].behavior === undefined || search[i].behavior === null) {
+ return [null];
+ }
+ returnString1D.push(data[Number(search[i].behavior)]);
}
return returnString1D;
}
-
/**
* @brief member function to find the output for a certain actionID for state 'none'
- * @param data :any an object containing all data read from a .keylayout file
+ * @param data an object containing all data read from a .keylayout file
* @param search :string an actionId to be found
* @return a string containing the output character
*/
- public getOutputFromActionIdNone(data: any, search: string): string {
+ public getOutputFromActionIdNone(data: Keylayout.KeylayoutXMLSourceFile, search: string): string {
let OutputValue: string = "";
- for (let i = 0; i < data.keyboard.actions.action.length; i++) {
- if (data.keyboard.actions.action[i]['id'] === search) {
- for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) {
- if (data.keyboard.actions.action[i].when[j]['state'] === "none") {
- if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) {
- OutputValue = data.keyboard.actions.action[i].when[j]['output'];
- }
+
+ if (!data.keyboard?.actions?.action) {
+ return OutputValue;
+ }
+
+ for (const action of data.keyboard.actions.action as Keylayout.KL_Action[]) {
+ if (action['id'] === search) {
+ for (const when of action.when as Keylayout.KL_When[]) {
+ if ((when['state'] === "none") && (when['output'] !== undefined)) {
+ OutputValue = when['output'];
}
}
}
@@ -852,11 +864,11 @@ export class KeylayoutToKmnConverter {
/**
* @brief member function to return array of [Keycode,Keyname,actionId,actionIDIndex, output] for a given actionID in of [ actionID,state,output]
- * @param data :any - an object containing all data read from a .keylayout file
+ * @param data an object containing all data read from a .keylayout file
* @param search :idStateOutputObject[] - array of [{ actionID,state,output }]
* @return a KeylayoutFileData[] containing [{Keycode,Keyname,actionId,actionID, output}]
*/
- public getKeyActionOutputArrayFromActionStateOutputArray(data: any, search: ActionStateOutput[]): KeylayoutFileData[] {
+ public getKeyActionOutputArrayFromActionStateOutputArray(data: Keylayout.KeylayoutXMLSourceFile, search: ActionStateOutput[]): KeylayoutFileData[] {
if ((search === undefined) || (search === null))
return [];
@@ -867,7 +879,7 @@ export class KeylayoutToKmnConverter {
for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) {
for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) {
if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search[k].id &&
- data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'] <= KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER) {
+ Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code']) <= KeylayoutToKmnConverter.MAX_KEY_IDENTIFIER) {
const singleDataSet = {
keyCode: data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'],
key: this.mapUkeleleKeycodeToVK(Number(data.keyboard.keyMapSet[0].keyMap[i].key[j]['code'])),
@@ -885,24 +897,26 @@ export class KeylayoutToKmnConverter {
/**
* @brief member function to get an array of all actionId-output pairs for a certain state
- * @param data : any an object containing all data read from a .keylayout file
+ * @param data an object containing all data read from a .keylayout file
* @param search : string a 'state' to be found
* @return an array: idStateOutputObject[] containing all [{actionId, state, output}] for a certain state
*/
- public getActionStateOutputArrayFromActionState(data: any, search: string): ActionStateOutput[] {
+ public getActionStateOutputArrayFromActionState(data: Keylayout.KeylayoutXMLSourceFile, search: string): ActionStateOutput[] {
const actionStateOutput: ActionStateOutput[] = [];
-
- for (let i = 0; i < data.keyboard.actions.action.length; i++) {
- for (let j = 0; j < data.keyboard.actions.action[i].when.length; j++) {
- if (data.keyboard.actions.action[i].when[j]['state'] === search) {
- if (data.keyboard.actions.action[i].when[j]['output'] !== undefined) {
- const singleDataSet = {
- id: data.keyboard.actions.action[i]['id'],
- state: data.keyboard.actions.action[i].when[j]['state'],
- output: data.keyboard.actions.action[i].when[j]['output']
- };
- actionStateOutput.push(singleDataSet);
+ if (search !== "none" && data.keyboard?.actions?.action) {
+ for (const action of data.keyboard.actions.action) {
+ if (action.when) {
+ for (const when of action.when) {
+ if ((when['state'] === search) && (when['output'] !== undefined)) {
+ const singleDataSet = {
+ id: action['id'],
+ state: when['state'],
+ output: when['output']
+ };
+ actionStateOutput.push(singleDataSet as ActionStateOutput);
+ }
}
+
}
}
}
@@ -911,12 +925,12 @@ export class KeylayoutToKmnConverter {
/**
* @brief member function to create an 2D array of [KeyName,actionId,behavior,modifier,output]
- * @param data : any an object containing all data read from a .keylayout file
+ * @param data an object containing all data read from a .keylayout file
* @param search : array of [{keycode,keyname,actionId,behavior,output}] to be found
* @param isCAPSused : boolean flag to indicate if CAPS is used in a keylayout file or not
* @return an array: KeylayoutFileData[] containing [{KeyName,actionId,behavior,modifier,output}]
*/
- public getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(data: any, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] {
+ public getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(data: Keylayout.KeylayoutXMLSourceFile, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] {
const keyBehaviorModOutput = [];
if (!((search === undefined) || (search === null) || (search.length === 0))) {
for (let i = 0; i < search.length; i++) {
@@ -945,20 +959,20 @@ export class KeylayoutToKmnConverter {
unique.push(o);
}
return unique;
- }, []);
+ }, [] as KeylayoutFileData[]);
return uniquekeyBehaviorModOutput;
}
/**
* @brief member function to create an array of [actionID, output, behavior,keyname,modifier] for a given actionId
- * @param data : any - an object containing all data read from a .keylayout file
- * @param modi : any - an array of modifiers
+ * @param data an object containing all data read from a .keylayout file
+ * @param modi an array of modifiers
* @param search : string - an actionId to be found
* @param outchar : string - the output character
* @param isCAPSused : boolean - flag to indicate if CAPS is used in a keylayout file or not
* @return an array: KeylayoutFileData[] containing [{actionID,output, behavior,keyname,modifier}]
*/
- public getActionOutputBehaviorKeyModiFromActionIDStateOutput(data: any, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] {
+ public getActionOutputBehaviorKeyModiFromActionIDStateOutput(data: Keylayout.KeylayoutXMLSourceFile, modi: string[][], search: string, outchar: string, isCapsused: boolean): KeylayoutFileData[] {
const actionOutputBehaviorKeyModi = [];
if ((!modi) || (search === "") || (search === undefined)) {
return [];
@@ -967,8 +981,8 @@ export class KeylayoutToKmnConverter {
for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) {
for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) {
if (data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'] === search) {
- for (let k = 0; k < modi[data.keyboard.keyMapSet[0].keyMap[i]['index']].length; k++) {
- const behaviorIdx: number = data.keyboard.keyMapSet[0].keyMap[i]['index'];
+ for (let k = 0; k < modi[Number(data.keyboard.keyMapSet[0].keyMap[i]['index'])].length; k++) {
+ const behaviorIdx: number = Number(data.keyboard.keyMapSet[0].keyMap[i]['index']);
const singleDataSet = {
outchar: outchar,
actionId: data.keyboard.keyMapSet[0].keyMap[i].key[j]['action'],
@@ -996,18 +1010,18 @@ export class KeylayoutToKmnConverter {
unique.push(o);
}
return unique;
- }, []);
+ }, [] as KeylayoutFileData[]);
return uniqueactionOutputBehaviorKey;
}
/**
* @brief member function to create an array of [{keycode,behavior}] for a given actionId
- * @param data : any - an object containing all data read from a .keylayout file
+ * @param data an object containing all data read from a .keylayout file
* @param search : string - an actionId to be found
* @return an array: KeylayoutFileData[] containing [{keycode,behavior}]
*/
- public getKeyModifierArrayFromActionID(data: any, search: string): KeylayoutFileData[] {
+ public getKeyModifierArrayFromActionID(data: Keylayout.KeylayoutXMLSourceFile, search: string): KeylayoutFileData[] {
const mapIndexObject1D: KeylayoutFileData[] = [];
for (let i = 0; i < data.keyboard.keyMapSet[0].keyMap.length; i++) {
for (let j = 0; j < data.keyboard.keyMapSet[0].keyMap[i].key.length; j++) {
diff --git a/developer/src/kmc-convert/test/data/keylayout.dtd b/developer/src/kmc-convert/test/data/keylayout.dtd
index e60fa8c51c..9a734b11b8 100644
--- a/developer/src/kmc-convert/test/data/keylayout.dtd
+++ b/developer/src/kmc-convert/test/data/keylayout.dtd
@@ -4,29 +4,86 @@
* 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'
+ * -->
-
-
-
-
-
+
+
+
+
+
+
+
-
-
+
+
+
+
-
-
+
+
+
+
+
+
+
-
+
+
+
+
-
-
+
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts
index c2f9fa5352..a7010ef1e7 100644
--- a/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts
+++ b/developer/src/kmc-convert/test/keylayout-to-kmn-converter.tests.ts
@@ -186,24 +186,6 @@ describe('KeylayoutToKmnConverter', function () {
assert.isNull(convertedEmpty);
});
- it('should return empty on only modifiers as input', async function () {
- const convertedMod = sut.convertBound.convert({
- keylayoutFilename: '',
- modifiers: [['caps'], ['Shift'], ['command']],
- rules: []
- }, '');
- assert.isNull(convertedMod);
- });
-
- it('should return empty on only rules as input', async function () {
- const convertedRule = sut.convertBound.convert({
- keylayoutFilename: '',
- modifiers: [],
- rules: [['C0', '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_A', 'A']]
- }, '');
- assert.isNull(convertedRule);
- });
-
it('should return empty array of rules on null input', async function () {
const convertedRule = sut.convertBound.convert(null, 'ABC.kmn');
assert.isNull(convertedRule);
@@ -350,13 +332,14 @@ describe('KeylayoutToKmnConverter', function () {
[[{ key: '999', behavior: null }], [null]],
[[{ key: '0', behavior: -999 }], [null]],
[[{ key: '0', behavior: null }], [null]],
+ [[{ key: '0', behavior: undefined }], [null]],
[[], []],
].forEach(function (values) {
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 KeylayoutFileData[]);
+ const result = sut.getModifierArrayFromKeyModifierArray(converted.modifiers, values[0] as unknown as KeylayoutFileData[]);
assert.deepStrictEqual(JSON.stringify(result), JSON.stringify(values[1]));
});
});
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 0eb23c88b4..ede21c9b9a 100644
--- a/developer/src/kmc-convert/test/kmn-file-writer.tests.ts
+++ b/developer/src/kmc-convert/test/kmn-file-writer.tests.ts
@@ -74,7 +74,7 @@ describe('KmnFileWriter', function () {
["ሴ", 'ሴ'],
["😎", '😎'],
["", '\u0002'],
- ["",undefined ],
+ ["", undefined],
["a", 'a'],
["ሴ", 'ሴ'],
["😆", '😆'],
@@ -148,9 +148,9 @@ describe('KmnFileWriter', function () {
['c WARNING: unavailable modifier : here: '],
['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']],
- ].forEach(function (values: any, index: number) {
- it(('rule " ' + values[0][0].ruleType + ' "') + 'should create "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () {
- const result: string[] = sutW.reviewRules(values[0], 0);
+ ].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);
assert.equal(result[0], values[1][0]);
assert.equal(result[1], values[2][0]);
assert.equal(result[2], values[3][0]);
@@ -313,9 +313,9 @@ describe('KmnFileWriter', function () {
[''],
["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]],
- ].forEach(function (values: any, index: number) {
- it('rule ' + values[0][0].ruleType + ' should create " ' + ' "' + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () {
- const result: string[] = sutW.reviewRules(values[0], 1);
+ ].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);
assert.equal(result[0], values[1][0]);
assert.equal(result[1], values[2][0]);
assert.equal(result[2], values[3][0]);
@@ -333,9 +333,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: any, index: number) {
- it(('rule ' + values[0][0].ruleType + ' should create " ' + ' "') + values[1] + ' | ' + values[2] + ' | ' + values[3] + '"', async function () {
- const result: string[] = sutW.reviewRules(values[0], 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.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]);
@@ -432,13 +432,13 @@ describe('KmnFileWriter', function () {
"dk(B2) + [NCAPS RALT K_A] > 'â'\n\n"
]
],
- ].forEach(function (values: any) {
+ ].forEach(function (values: (string[] | Rule[])[], index: number) {
it(('an array of Rules should create a set of kmn rules '), async function () {
const data: ProcessedData = {
keylayoutFilename: "",
kmnFilename: "",
modifiers: [[]],
- rules: values[0]
+ rules: values[0] as Rule[]
};
const result1 = sutW.writeDataRules(data);
assert.isTrue(result1 === values[1][0]);
diff --git a/resources/standards-data/keylayout/dtd/keylayout.xsd b/resources/standards-data/keylayout/dtd/keylayout.xsd
index 48e84f3f15..554d5bbd27 100644
--- a/resources/standards-data/keylayout/dtd/keylayout.xsd
+++ b/resources/standards-data/keylayout/dtd/keylayout.xsd
@@ -8,7 +8,10 @@
-
+
+
@@ -63,7 +66,7 @@
-
+
@@ -83,7 +86,7 @@
-
+