mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-14 19:47:43 +00:00
Merge pull request #16073 from keymanapp/feat/developer/kmc-convert-warningMessages
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled
Some checks failed
Keyman Build Summary / Summarize build status checks (push) Has been cancelled
feat(developer): reviewRules: return object instead of string[] 😎
This commit is contained in:
commit
786887b053
11 changed files with 817 additions and 2471 deletions
|
|
@ -18,9 +18,9 @@ const SevError = CompilerErrorSeverity.Error | Namespace;
|
|||
export class ConverterMessages {
|
||||
|
||||
static ERROR_FileNotFound = SevError | 0x0003;
|
||||
static Error_FileNotFound = (o: { inputFilename: string; }) => m(
|
||||
static Error_FileNotFound = (o?: { inputFilename: string | null; }) => m(
|
||||
this.ERROR_FileNotFound,
|
||||
`Input filename '${def(o.inputFilename)}' does not exist or could not be loaded.`
|
||||
`Input filename '${def(o?.inputFilename)}' does not exist or could not be loaded.`
|
||||
);
|
||||
|
||||
static ERROR_InvalidFile = SevError | 0x0004;
|
||||
|
|
|
|||
|
|
@ -68,9 +68,9 @@ export class Converter implements KeymanCompiler {
|
|||
return null;
|
||||
}
|
||||
|
||||
const ConverterClass = ConverterClassFactory.find(inputFilename, outputFilename);
|
||||
const ConverterClass = ConverterClassFactory.find(inputFilename, outputFilename ?? '.kmn');
|
||||
if (!ConverterClass) {
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_NoConverterFound({ inputFilename, outputFilename }));
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_NoConverterFound({ inputFilename, outputFilename: outputFilename ?? '' }));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,9 +17,10 @@ export class KeylayoutFileReader {
|
|||
|
||||
constructor(private callbacks: CompilerCallbacks /*,private options: CompilerOptions*/) { };
|
||||
|
||||
|
||||
/**
|
||||
* @brief helper function to find a specific keyMap index in a keyMapSet
|
||||
* @brief Helper function to check if a specific keyMap index exists in a keyMapSet.
|
||||
* This is neccessary because the amount of <keyMap index> must correspond to
|
||||
* the amount of <keyMapSelect mapIndex>.
|
||||
* @param jsonObj the read keylayout data to be checked
|
||||
* @param keyMapSelect the keyMapSelect element to find in keyMapSet
|
||||
* @return true if the keyMapSet element is found, false if not
|
||||
|
|
@ -36,7 +37,9 @@ export class KeylayoutFileReader {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief helper function to find a specific keyMapSelect index in a modifierMap
|
||||
* @brief Helper function to check if a specific keyMapSelect index exists in a modifierMap.
|
||||
* This is neccessary because the amount of <keyMap index> must correspond to
|
||||
* the amount of <keyMapSelect mapIndex>.
|
||||
* @param jsonObj the read keylayout data to be checked
|
||||
* @param keyMap the keyMap element to find in modifierMap
|
||||
* @return true if the keyMap element is found, false if not
|
||||
|
|
@ -53,8 +56,8 @@ export class KeylayoutFileReader {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief member function checking if all keyMapSelect elements have a corresponding keyMap
|
||||
* element in the .keylayout file (if not, the .keylayout file is invalid and will not be converted)
|
||||
* @brief member function checking if all keyMapSelect elements have exact one corresponding keyMap element (per keyMapSet)
|
||||
* in the .keylayout file (if not, the .keylayout file is invalid and will not be converted)
|
||||
* see TN2056 (https://developer.apple.com/library/archive/technotes/tn2056/_index.html#//apple_ref/doc/uid/DTS10003085-CH1-SUBSECTION7)
|
||||
* @param jsonObj the read keylayout data to be checked
|
||||
* @return true if all keyMapSelect elements have a corresponding keyMap element, false if not
|
||||
|
|
@ -82,6 +85,10 @@ export class KeylayoutFileReader {
|
|||
* @returns true if valid, false if invalid
|
||||
*/
|
||||
public validate(source: Keylayout.KeylayoutXMLSourceFile, inputFilename: string): boolean {
|
||||
if (!source) {
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename: inputFilename }));
|
||||
return false;
|
||||
}
|
||||
if (!SchemaValidators.default.keylayout(source)) {
|
||||
for (const err of (<any>SchemaValidators.default.keylayout).errors) {
|
||||
this.callbacks.reportMessage(DeveloperUtilsMessages.Error_InvalidXml({
|
||||
|
|
@ -148,7 +155,7 @@ export class KeylayoutFileReader {
|
|||
* @param inputFilename the ukelele .keylayout-file to be parsed
|
||||
* @return in case of success: json object containing data of the .keylayout file; else null
|
||||
*/
|
||||
public read(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile {
|
||||
public read(source: Uint8Array): Keylayout.KeylayoutXMLSourceFile | null {
|
||||
|
||||
try {
|
||||
const data = new TextDecoder().decode(source);
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ export class KeylayoutToKmnConverter {
|
|||
* @param outputFilename the resulting keyman .kmn-file
|
||||
* @return null on success
|
||||
*/
|
||||
async run(inputFilename: string, outputFilename?: string): Promise<ConverterToKmnResult> {
|
||||
async run(inputFilename: string, outputFilename?: string): Promise<ConverterToKmnResult | null> {
|
||||
|
||||
if (!inputFilename) {
|
||||
throw new Error('Input filename is required');
|
||||
|
|
@ -118,7 +118,7 @@ export class KeylayoutToKmnConverter {
|
|||
const KeylayoutReader = new KeylayoutFileReader(this.callbacks/*, this.options*/);
|
||||
|
||||
const binaryData = this.callbacks.loadFile(inputFilename);
|
||||
const jsonO: Keylayout.KeylayoutXMLSourceFile = KeylayoutReader.read(binaryData);
|
||||
const jsonO: Keylayout.KeylayoutXMLSourceFile | null = KeylayoutReader.read(binaryData);
|
||||
|
||||
if (!jsonO) {
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_UnableToReadFile({ inputFilename: inputFilename }));
|
||||
|
|
@ -128,7 +128,7 @@ export class KeylayoutToKmnConverter {
|
|||
if (!KeylayoutReader.validate(jsonO, inputFilename)) {
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
} catch (e: any) {
|
||||
this.callbacks.reportMessage(ConverterMessages.Error_InvalidFile({ errorText: e.toString() }));
|
||||
return null;
|
||||
}
|
||||
|
|
@ -137,10 +137,16 @@ export class KeylayoutToKmnConverter {
|
|||
const kmnFileWriter = new KmnFileWriter(this.callbacks, this.options);
|
||||
|
||||
// write to object/ConverterToKmnResult
|
||||
const outputKmn = kmnFileWriter.write(processedData);
|
||||
const outputKmn = processedData ? kmnFileWriter.write(processedData) : null;
|
||||
|
||||
if (!processedData || !outputKmn) {
|
||||
return null;
|
||||
}
|
||||
const result: ConverterToKmnResult = {
|
||||
artifacts: {
|
||||
kmn: { data: outputKmn, filename: processedData.kmnFilename }
|
||||
kmn: {
|
||||
data: outputKmn, filename: processedData.kmnFilename
|
||||
}
|
||||
}
|
||||
};
|
||||
return result;
|
||||
|
|
@ -151,7 +157,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: Keylayout.KeylayoutXMLSourceFile, inputfilename: string, outputFilename?: string): ProcessedData {
|
||||
private convert(jsonObj: Keylayout.KeylayoutXMLSourceFile, inputfilename: string, outputFilename?: string): ProcessedData | null {
|
||||
// modifiers for each behavior
|
||||
const modifierBehavior: string[][] = [];
|
||||
|
||||
|
|
@ -197,7 +203,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: Keylayout.KeylayoutXMLSourceFile): ProcessedData {
|
||||
public createRuleData(dataUkelele: ProcessedData, jsonObj: Keylayout.KeylayoutXMLSourceFile): ProcessedData | null {
|
||||
|
||||
const rules: Rule[] = [];
|
||||
let dkCounterC3: number = 0;
|
||||
|
|
@ -228,7 +234,7 @@ export class KeylayoutToKmnConverter {
|
|||
// ...............e. g. <key code="1" output="s"/> ...............................................................................
|
||||
// ...............................................................................................................................
|
||||
|
||||
if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] !== undefined) {
|
||||
if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] !== undefined) {
|
||||
|
||||
// loop modifiers
|
||||
for (let l = 0; l < dataUkelele.modifiers[i].length; l++) {
|
||||
|
|
@ -292,8 +298,8 @@ export class KeylayoutToKmnConverter {
|
|||
/* dk for C2*/ 0,
|
||||
/* unique B */ 0,
|
||||
|
||||
/* modifierKey*/ b1ModifierKeyObj[m].modifier,
|
||||
/* key */ b1ModifierKeyObj[m].key,
|
||||
/* modifierKey*/ b1ModifierKeyObj[m].modifier ?? "",
|
||||
/* key */ b1ModifierKeyObj[m].key ?? "",
|
||||
/* output */ new TextEncoder().encode(outputchar)
|
||||
);
|
||||
if ((outputchar !== undefined) && (outputchar !== "undefined") && (outputchar !== "")) {
|
||||
|
|
@ -338,7 +344,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) as string[][];
|
||||
// ........................................................................................................................................................................................
|
||||
|
||||
|
||||
|
|
@ -372,8 +378,8 @@ export class KeylayoutToKmnConverter {
|
|||
/* dk for C2*/ dkCounterC2++,
|
||||
/* unique B */ 0,
|
||||
|
||||
/* modifierKey*/ b1ModifierKeyObj[n4].modifier,
|
||||
/* key */ b1ModifierKeyObj[n4].key,
|
||||
/* modifierKey*/ b1ModifierKeyObj[n4].modifier ?? "",
|
||||
/* key */ b1ModifierKeyObj[n4].key ?? "",
|
||||
/* output */ new TextEncoder().encode(b1ModifierKeyObj[n4].outchar),
|
||||
);
|
||||
if ((b1ModifierKeyObj[n4].outchar !== undefined)
|
||||
|
|
@ -402,21 +408,22 @@ export class KeylayoutToKmnConverter {
|
|||
|
||||
// with actionId from above loop all 'action' and search for a state-next-pair ...................................................................................................................
|
||||
// e.g. in Block 5: find <when state="3" next="1"/> for action id a16 .............................................................................................................................
|
||||
for (let l = 0; l < jsonObj.keyboard.actions.action[b1ActionIndex].when.length; l++) {
|
||||
if ((jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'] !== "none")
|
||||
&& (jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'] !== undefined)) {
|
||||
if (jsonObj.keyboard.actions?.action?.[b1ActionIndex]?.when) {
|
||||
for (const when of jsonObj.keyboard.actions.action[b1ActionIndex].when) {
|
||||
if ((when['state'] !== "none")
|
||||
&& (when['next'] !== undefined)) {
|
||||
|
||||
// Data of Block Nr 5 ........................................................................................................................................................................
|
||||
// of this state-next-pair get value of next (next="1") and state="3" ........................................................................................................................
|
||||
/* e.g. state = 3 */ const b5ValueState: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['state'];
|
||||
/* e.g. next = 1 */ const b5ValueNext: string = jsonObj.keyboard.actions.action[b1ActionIndex].when[l]['next'];
|
||||
/* e.g. state = 3 */ const b5ValueState: string = when['state'] as string;
|
||||
/* e.g. next = 1 */ const b5ValueNext: string = when['next'];
|
||||
// ...........................................................................................................................................................................................
|
||||
|
||||
// Data of Block Nr 4 ........................................................................................................................................................................
|
||||
// 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) as string[][];
|
||||
// ...........................................................................................................................................................................................
|
||||
|
||||
// Data of Block Nr 3 ........................................................................................................................................................................
|
||||
|
|
@ -428,7 +435,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) as string[][];
|
||||
// ...........................................................................................................................................................................................
|
||||
// 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 <when state="1" output="â"/> ) .........................................
|
||||
|
|
@ -439,17 +446,17 @@ export class KeylayoutToKmnConverter {
|
|||
// create array[Keycode,Keyname,action id,actionIndex,output] and array[Keyname,action id,behavior,modifier,output] .........................................................................
|
||||
/* eg: ['49','K_SPACE','a0','0','Â'] */ const b1KeycodeObj: KeylayoutFileData[] = this.getKeyActionOutputArrayFromActionStateOutputArray(jsonObj, b6ActionIdObj);
|
||||
/* eg: ['K_SPACE','a0','0','NCAPS','Â'] */ const b1ModifierKeyObj: KeylayoutFileData[] = this.getKeyBehaviorModOutputArrayFromKeyActionBehaviorOutputArray(jsonObj, b1KeycodeObj, isCapsused);
|
||||
// ...........................................................................................................................................................................................
|
||||
// ...........................................................................................................................................................................................
|
||||
|
||||
for (let n1 = 0; n1 < b2PrevDeadkeyModifierObj.length; n1++) {
|
||||
for (let n2 = 0; n2 < b2PrevDeadkeyModifierObj[n1].length; n2++) {
|
||||
for (let n3 = 0; n3 < b2PrevDeadkeyObj.length; n3++) {
|
||||
for (let n4 = 0; n4 < b4DeadkeyModifierObj.length; n4++) {
|
||||
for (let n5 = 0; n5 < b4DeadkeyModifierObj[n4].length; n5++) {
|
||||
for (let n6 = 0; n6 < b4DeadkeyObj.length; n6++) {
|
||||
for (let n7 = 0; n7 < b1ModifierKeyObj.length; n7++) {
|
||||
for (let n1 = 0; n1 < b2PrevDeadkeyModifierObj.length; n1++) {
|
||||
for (let n2 = 0; n2 < b2PrevDeadkeyModifierObj[n1].length; n2++) {
|
||||
for (let n3 = 0; n3 < b2PrevDeadkeyObj.length; n3++) {
|
||||
for (let n4 = 0; n4 < b4DeadkeyModifierObj.length; n4++) {
|
||||
for (let n5 = 0; n5 < b4DeadkeyModifierObj[n4].length; n5++) {
|
||||
for (let n6 = 0; n6 < b4DeadkeyObj.length; n6++) {
|
||||
for (let n7 = 0; n7 < b1ModifierKeyObj.length; n7++) {
|
||||
|
||||
ruleObj = new Rule(
|
||||
ruleObj = new Rule(
|
||||
/* ruleType */ "C3",
|
||||
/* modifierPrevDeadkey*/ this.createKmnModifier(b2PrevDeadkeyModifierObj[n1][n2], isCapsused),
|
||||
/* prevDeadkey */ this.mapUkeleleKeycodeToVK(Number(b2PrevDeadkeyObj[n3].key)),
|
||||
|
|
@ -461,14 +468,15 @@ export class KeylayoutToKmnConverter {
|
|||
/* dk for C2*/ 0,
|
||||
/* unique B */ 0,
|
||||
|
||||
/* modifierKey*/ b1ModifierKeyObj[n7].modifier,
|
||||
/* key */ b1ModifierKeyObj[n7].key,
|
||||
/* modifierKey*/ b1ModifierKeyObj[n7].modifier ?? "",
|
||||
/* key */ b1ModifierKeyObj[n7].key ?? "",
|
||||
/* output */ new TextEncoder().encode(b1ModifierKeyObj[n7].outchar),
|
||||
);
|
||||
if ((b1ModifierKeyObj[n7].outchar !== undefined)
|
||||
&& (b1ModifierKeyObj[n7].outchar !== "undefined")
|
||||
&& (b1ModifierKeyObj[n7].outchar !== "")) {
|
||||
rules.push(ruleObj);
|
||||
);
|
||||
if ((b1ModifierKeyObj[n7].outchar !== undefined)
|
||||
&& (b1ModifierKeyObj[n7].outchar !== "undefined")
|
||||
&& (b1ModifierKeyObj[n7].outchar !== "")) {
|
||||
rules.push(ruleObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -930,6 +938,7 @@ export class KeylayoutToKmnConverter {
|
|||
* @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: Keylayout.KeylayoutXMLSourceFile, search: KeylayoutFileData[], isCAPSused: boolean): KeylayoutFileData[] {
|
||||
const keyBehaviorModOutput = [];
|
||||
if (!((search === undefined) || (search === null) || (search.length === 0))) {
|
||||
|
|
@ -948,7 +957,7 @@ export class KeylayoutToKmnConverter {
|
|||
}
|
||||
}
|
||||
// remove duplicates
|
||||
const uniquekeyBehaviorModOutput = keyBehaviorModOutput.reduce((unique, o) => {
|
||||
const uniquekeyBehaviorModOutput = keyBehaviorModOutput.reduce<KeylayoutFileData[]>((unique, o) => {
|
||||
if (!unique.some(obj =>
|
||||
obj.actionId === o.actionId &&
|
||||
obj.key === o.key &&
|
||||
|
|
@ -999,7 +1008,7 @@ export class KeylayoutToKmnConverter {
|
|||
//.............................................................................
|
||||
|
||||
// remove duplicates
|
||||
const uniqueactionOutputBehaviorKey = actionOutputBehaviorKeyModi.reduce((unique, o) => {
|
||||
const uniqueactionOutputBehaviorKey = actionOutputBehaviorKeyModi.reduce<KeylayoutFileData[]>((unique, o) => {
|
||||
if (!unique.some(obj =>
|
||||
obj.outchar === o.outchar &&
|
||||
obj.actionId === o.actionId &&
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -24,6 +24,9 @@
|
|||
<key code="1" output="U+1F603"/>
|
||||
<key code="2" output="😂"/>
|
||||
<key code="3" output="😀"/>
|
||||
<key code="3" output="U+0001"/>
|
||||
<key code="4" output=""/><!--should give unexpected entity as fast xml parser reads it to '' -->
|
||||
|
||||
</keyMap>
|
||||
</keyMapSet>
|
||||
<actions>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
<?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
|
||||
more keyMapSelect than KeyMap
|
||||
|
||||
-->
|
||||
<keyboard group="126" id="-1272" name="Test_DifferentAmountOfMapSelectInKeyMapERROR" maxout="1">
|
||||
<layouts>
|
||||
<layout first="0" last="0" mapSet="138" modifiers="30"/>
|
||||
</layouts>
|
||||
<!-- different amount of tags MapSelect(2) vs. KeyMap(3) -->
|
||||
<modifierMap id="30" defaultIndex="0">
|
||||
<keyMapSelect mapIndex="0">
|
||||
<modifier keys=""/>
|
||||
<modifier keys="shift? caps? "/>
|
||||
</keyMapSelect>
|
||||
<keyMapSelect mapIndex="1">
|
||||
<modifier keys="caps"/>
|
||||
</keyMapSelect>
|
||||
</modifierMap>
|
||||
|
||||
<!-- different amount of tags MapSelect(2) vs. KeyMap(3) -->
|
||||
<keyMapSet id="ANSI">
|
||||
<keyMap index="0">
|
||||
<key code="0" action="A_9"/>
|
||||
<key code="1" output="s"/>
|
||||
<key code="2" output="d"/>
|
||||
<key code="3" output="f"/>
|
||||
<key code="4" output="h"/>
|
||||
<key code="9" output="v"/>
|
||||
<key code="10" output="\"/>
|
||||
</keyMap>
|
||||
<keyMap index="1">
|
||||
<key code="0" action="A_1"/>
|
||||
<key code="1" output="S"/>
|
||||
<key code="2" output="D"/>
|
||||
<key code="3" output="F"/>
|
||||
<key code="4" output="@"/>
|
||||
<key code="5" output="G"/>
|
||||
<key code="6" output="Z"/>
|
||||
<key code="7" output="X"/>
|
||||
<key code="8" output="C"/>
|
||||
<key code="9" output="V"/>
|
||||
<key code="10" output="\"/>
|
||||
</keyMap>
|
||||
</keyMapSet>
|
||||
<keyMapSet id="JIS">
|
||||
<keyMap index="0">
|
||||
<key code="0" action="A_9"/>
|
||||
<key code="1" output="s"/>
|
||||
<key code="2" output="d"/>
|
||||
<key code="3" output="f"/>
|
||||
<key code="4" output="h"/>
|
||||
<key code="9" output="v"/>
|
||||
<key code="10" output="\"/>
|
||||
</keyMap>
|
||||
<keyMap index="1">
|
||||
<key code="0" action="A_1"/>
|
||||
<key code="1" output="ሴ"/>
|
||||
<key code="2" output="😎"/>
|
||||
</keyMap>
|
||||
</keyMapSet>
|
||||
<actions>
|
||||
<action id="A_1">
|
||||
<when state="none" output="A"/>
|
||||
</action>
|
||||
<action id="A_9">
|
||||
<when state="none" output="A"/>
|
||||
</action>
|
||||
</actions>
|
||||
<terminators>
|
||||
<when state="1" output="ˆ"/>
|
||||
</terminators>
|
||||
</keyboard>
|
||||
|
|
@ -12,6 +12,7 @@ import { assert } from 'chai';
|
|||
import { Keylayout } from "@keymanapp/developer-utils";
|
||||
import { compilerTestCallbacks, makePathToFixture } from './helpers/index.js';
|
||||
import { KeylayoutFileReader } from '../src/keylayout-to-kmn/keylayout-file-reader.js';
|
||||
import { KL_KeyMap, KL_KeyMapSelect } from "../../common/web/utils/src/types/keylayout/keylayout-xml.js";
|
||||
|
||||
describe('KeylayoutFileReader', function () {
|
||||
|
||||
|
|
@ -27,6 +28,50 @@ describe('KeylayoutFileReader', function () {
|
|||
const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename);
|
||||
assert.isTrue(validated);
|
||||
});
|
||||
|
||||
it('validate() should return false on inputfile with unknown tags', async function () {
|
||||
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const inputFilename = makePathToFixture('../data/Test_unknownTags.keylayout');
|
||||
const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
|
||||
const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename);
|
||||
assert.isFalse(validated);
|
||||
});
|
||||
|
||||
it('validate() should return false on inputfile with additional tags', async function () {
|
||||
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const inputFilename = makePathToFixture('../data/Test_additionalTags.keylayout');
|
||||
const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
|
||||
const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename);
|
||||
assert.isFalse(validated);
|
||||
});
|
||||
it('validate() should return false on inputfile with missing tags', async function () {
|
||||
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const inputFilename = makePathToFixture('../data/Test_missingTags.keylayout');
|
||||
const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
|
||||
const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename);
|
||||
assert.isFalse(validated);
|
||||
});
|
||||
it('validate() should return false on no entries in action-when', async function () {
|
||||
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const inputFilename = makePathToFixture('../data/Test_noActionWhen.keylayout');
|
||||
const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
|
||||
const validated = sutR.validate(result as Keylayout.KeylayoutXMLSourceFile, inputFilename);
|
||||
assert.isFalse(validated);
|
||||
});
|
||||
it('validate() should return false on null as input', async function () {
|
||||
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const inputFilename = makePathToFixture('../data/Test_noActionWhen.keylayout');
|
||||
//const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
|
||||
const validated = sutR.validate(null, inputFilename);
|
||||
assert.isFalse(validated);
|
||||
});
|
||||
it('validate() should return false on undefined as input', async function () {
|
||||
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const inputFilename = makePathToFixture('../data/Test_noActionWhen.keylayout');
|
||||
//const result: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
|
||||
const validated = sutR.validate(undefined, inputFilename);
|
||||
assert.isFalse(validated);
|
||||
});
|
||||
});
|
||||
|
||||
describe('validate() should return false on inputfiles with errors ', function () {
|
||||
|
|
@ -86,6 +131,84 @@ describe('KeylayoutFileReader', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('findMapIndexinKeymap ', function () {
|
||||
const keyMapSelect: KL_KeyMapSelect = {
|
||||
mapIndex: '',
|
||||
modifier: []
|
||||
};
|
||||
|
||||
keyMapSelect.modifier.push({ keys: 'caps' });
|
||||
keyMapSelect.modifier.push({ keys: 'rightOption' });
|
||||
keyMapSelect.modifier.push({ keys: 'rightShift caps' });
|
||||
|
||||
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const inputFilename = makePathToFixture('../data/Test.keylayout');
|
||||
const jsonO: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
|
||||
[
|
||||
['0', true],
|
||||
['7', true],
|
||||
['999', false],
|
||||
['A', false],
|
||||
[123, false],
|
||||
['', false],
|
||||
[null, false],
|
||||
[undefined, false],
|
||||
].forEach(function (values) {
|
||||
it(("findMapIndexinKeymap(keyMapSelect.mapIndex = '" + values[0] + "')").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () {
|
||||
keyMapSelect.mapIndex = values[0] as string;
|
||||
const result = sutR.findMapIndexinKeymap(jsonO as Keylayout.KeylayoutXMLSourceFile, keyMapSelect);
|
||||
assert.equal(result, values[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('findIndexinKeymapSelect ', function () {
|
||||
const keyMap: KL_KeyMap = {
|
||||
index: '',
|
||||
key: []
|
||||
};
|
||||
keyMap.key.push({ code: '0', output: 'A' });
|
||||
keyMap.key.push({ code: '1', action: 'S' });
|
||||
keyMap.key.push({ code: '2', output: 'D' });
|
||||
|
||||
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
const inputFilename = makePathToFixture('../data/Test.keylayout');
|
||||
const jsonO: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(inputFilename));
|
||||
[
|
||||
['0', true],
|
||||
['7', true],
|
||||
['999', false],
|
||||
['A', false],
|
||||
[123, false],
|
||||
['', false],
|
||||
[null, false],
|
||||
[undefined, false],
|
||||
].forEach(function (values) {
|
||||
it(("findIndexinKeymapSelect(keyMap.index = '" + values[0] + "')").padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () {
|
||||
keyMap.index = values[0] as string;
|
||||
const result = sutR.findIndexinKeymapSelect(jsonO as Keylayout.KeylayoutXMLSourceFile, keyMap);
|
||||
assert.equal(result, values[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkForCorrespondingElements ', function () {
|
||||
const sutR = new KeylayoutFileReader(compilerTestCallbacks);
|
||||
[
|
||||
['../data/Test.keylayout', true],
|
||||
['../data/Test_sameKeyMapAndKeyMapselectAndJisERROR.keylayout', true],
|
||||
['../data/Test_moreKeymapSelectThanKeymapERROR.keylayout', false],
|
||||
['../data/Test_moreKeyMapThanKeyMapselectERROR.keylayout', false],
|
||||
['../data/Test_moreKeyMapThanKeyMapselectAndJisERROR.keylayout', false],
|
||||
].forEach(function (values) {
|
||||
it(("checkForCorrespondingElements in " + values[0]).padEnd(40, " ") + "should return " + "'" + values[1] + "'", async function () {
|
||||
const jsonO: Keylayout.KeylayoutXMLSourceFile | null = sutR.read(compilerTestCallbacks.loadFile(makePathToFixture(values[0] as string)));
|
||||
const result = sutR.checkForCorrespondingElements(jsonO as Keylayout.KeylayoutXMLSourceFile);
|
||||
assert.equal(result, values[1]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("read() check structure of returned JSON", function () {
|
||||
|
||||
it('read() should have the correct JSON structure', async function () {
|
||||
|
|
@ -96,7 +219,7 @@ describe('KeylayoutFileReader', function () {
|
|||
const result: Keylayout.KeylayoutXMLSourceFile = sutR.read(binaryData);
|
||||
|
||||
assert.isNotNull(result);
|
||||
assert.isTrue(result.keyboard !== null);
|
||||
assert.notEqual(result.keyboard, null);
|
||||
|
||||
for (let i = 0; i < result.keyboard.layouts.length; i++) {
|
||||
assert.isTrue(result.keyboard.layouts[i].layout.length > 0);
|
||||
|
|
@ -108,8 +231,8 @@ describe('KeylayoutFileReader', function () {
|
|||
for (let j = 0; j < result.keyboard.keyMapSet[i].keyMap.length; j++) {
|
||||
assert.isTrue(result.keyboard.keyMapSet[i].keyMap[j].key.length > 0);
|
||||
for (let k = 0; k < result.keyboard.keyMapSet[i].keyMap[j].key.length; k++) {
|
||||
assert.isTrue(result.keyboard.keyMapSet[i].keyMap[j].key[k]['action'] !== null
|
||||
|| result.keyboard.keyMapSet[i].keyMap[j].key[k]['output'] !== null);
|
||||
assert.isNotNull(result.keyboard.keyMapSet[i].keyMap[j].key[k]['action']);
|
||||
assert.isNotNull(result.keyboard.keyMapSet[i].keyMap[j].key[k]['output']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -124,8 +247,8 @@ describe('KeylayoutFileReader', function () {
|
|||
for (let i = 0; i < result.keyboard.modifierMap.length; i++) {
|
||||
assert.isTrue(result.keyboard.modifierMap[i].keyMapSelect.length > 0);
|
||||
for (let j = 0; j < result.keyboard.keyMapSet.length; j++) {
|
||||
assert.isTrue(result.keyboard.keyMapSet[j].keyMap.length
|
||||
=== result.keyboard.modifierMap[i].keyMapSelect.length);
|
||||
assert.equal(result.keyboard.keyMapSet[j].keyMap.length,
|
||||
result.keyboard.modifierMap[i].keyMapSelect.length);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -60,14 +60,13 @@ describe('KeylayoutToKmnConverter', function () {
|
|||
['../data/Test.keylayout'],
|
||||
].forEach(function (files) {
|
||||
it(files + " should give no errors ", async function () {
|
||||
sut.run(makePathToFixture(files[0]));
|
||||
// assert.isTrue(compilerTestCallbacks.messages.length === 1 && compilerTestCallbacks.messages[0].code === 5292037);
|
||||
await sut.run(makePathToFixture(files[0]));
|
||||
assert.isTrue(compilerTestCallbacks.messages.length === 0);
|
||||
await sut.run(makePathToFixture(files[0]));
|
||||
assert.equal(compilerTestCallbacks.messages.length, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('RunTestFiles resulting in errors ', function () {
|
||||
const sut = new KeylayoutToKmnConverter(compilerTestCallbacks, compilerTestOptions);
|
||||
[
|
||||
|
|
@ -97,7 +96,7 @@ describe('KeylayoutToKmnConverter', function () {
|
|||
['../data/Test_undefinedAction.keylayout'],
|
||||
].forEach(function (files) {
|
||||
it(files + " should give Error: undefined action detected", async function () {
|
||||
sut.run(makePathToFixture(files[0]));
|
||||
await sut.run(makePathToFixture(files[0]));
|
||||
assert.equal(compilerTestCallbacks.messages.length, 1);
|
||||
assert.equal(compilerTestCallbacks.messages[0].code, 5292040);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ describe('KmnFileWriter', function () {
|
|||
|
||||
it(('writeKmnFileHeader should return store text with filename ').padEnd(62, " ") + 'on correct input', async function () {
|
||||
const writtenCorrectName = sutW.writeKmnFileHeader(converted);
|
||||
assert.equal(writtenCorrectName, (outExpectedFirst + converted.keylayoutFilename + outExpectedLast));
|
||||
assert.equal(writtenCorrectName, (outExpectedFirst + (converted?.keylayoutFilename ?? "") + outExpectedLast));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -105,57 +105,48 @@ describe('KmnFileWriter', function () {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe('reviewRules messages', function () {
|
||||
const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
|
||||
[/*
|
||||
[
|
||||
[[new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'UNAVAILABLE', 'K_A', new TextEncoder().encode('A'))],
|
||||
[''],
|
||||
[''],
|
||||
['c WARNING: unavailable modifier : here: ']],
|
||||
['c WARNING: unavailable modifier here: ']],
|
||||
|
||||
[[new Rule("C1", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_B', new TextEncoder().encode('B'))],
|
||||
[''],
|
||||
[''],
|
||||
['c WARNING: unavailable modifier : here: ']],
|
||||
['c WARNING: unavailable modifier here: ']],
|
||||
|
||||
[[new Rule("C2", '', '', 0, 0, 'CAPS', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)],
|
||||
[''],
|
||||
[''],
|
||||
['c WARNING: unavailable modifier : here: ']],
|
||||
['c WARNING: unavailable modifier here: ']],
|
||||
|
||||
[[new Rule("C2", '', '', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)],
|
||||
[[new Rule("C2", '', '', 1, 1, 'UNAVAILABLE_dk', 'K_EQUAL', 2, 2, 'UNAVAILABLE', 'K_C', new TextEncoder().encode('C'),)],
|
||||
[''],
|
||||
['c WARNING: unavailable modifier : here: '],
|
||||
['c WARNING: unavailable modifier : here: ']],
|
||||
['c WARNING: unavailable modifier here: '],
|
||||
['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(A2) ) : unavailable modifier here: ']],
|
||||
|
||||
[[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)],
|
||||
['c WARNING: unavailable modifier : here: '],
|
||||
['c WARNING: unavailable modifier : here: '],
|
||||
['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(B0) ) : here: ']],
|
||||
[[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 1, 1, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)],
|
||||
['c WARNING: unavailable modifier here: '],
|
||||
['c WARNING: unavailable superior rule ( [UNAVAILABLE_prev_dk K_D] > dk(A1) ) : unavailable modifier here: '],
|
||||
['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(B0) ) : here: ']],
|
||||
|
||||
*/
|
||||
|
||||
[[new Rule("C3", 'UNAVAILABLE_prev_dk', 'K_D', 0, 0, 'UNAVAILABLE_dk', 'K_EQUAL', 0, 0, 'UNAVAIL', 'K_C', new TextEncoder().encode('D'),)],
|
||||
['c WARNING: unavailable modifier : here: '],
|
||||
['c WARNING: unavailable modifier : here: '],
|
||||
['c WARNING: unavailable superior rule ( [UNAVAILABLE_dk K_EQUAL] > dk(B0) ) : unavailable modifier : here: ']],
|
||||
|
||||
|
||||
|
||||
|
||||
[[new Rule("C3", 'CAPS', 'K_D', 0, 0, 'RALT', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)],
|
||||
[[new Rule("C3", 'CAPS', 'K_D', 1, 1, 'RALT', 'K_EQUAL', 0, 0, 'SHIFT', 'K_C', new TextEncoder().encode('D'),)],
|
||||
[''],
|
||||
[''],
|
||||
['']],
|
||||
|
||||
[[new Rule("C3", 'X', 'K_X', 0, 0, 'Y', 'K_Y', 0, 0, 'SHIFT', 'K_Z', new TextEncoder().encode('D'),)],
|
||||
['c WARNING: unavailable modifier : here: '],
|
||||
['c WARNING: unavailable modifier : here: '],
|
||||
['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']],
|
||||
[[new Rule("C3", 'X', 'K_X', 1, 1, 'Y', 'K_Y', 0, 0, 'SHIFT', 'K_Z', new TextEncoder().encode('D'),)],
|
||||
['c WARNING: unavailable modifier here: '],
|
||||
['c WARNING: unavailable superior rule ( [X K_X] > dk(A1) ) : unavailable modifier here: '],
|
||||
['c WARNING: unavailable superior rule ( [Y K_Y] > dk(B0) ) : here: ']],
|
||||
|
||||
].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[], 0);
|
||||
const result: string[] = sutW.unitTestEndpoints.reviewRules(values[0] as Rule[], 0).warningMessages;
|
||||
assert.equal(result[0], values[1][0]);
|
||||
assert.equal(result[1], values[2][0]);
|
||||
assert.equal(result[2], values[3][0]);
|
||||
|
|
@ -163,6 +154,7 @@ describe('KmnFileWriter', function () {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe('reviewRules messages duplicate and ambiguous', function () {
|
||||
const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
|
||||
[
|
||||
|
|
@ -170,9 +162,9 @@ describe('KmnFileWriter', function () {
|
|||
[[
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),],
|
||||
['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
["c WARNING: duplicate rule: earlier: dk(B0) + [SHIFT K_B] > dk(B0) here: "],
|
||||
["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]],
|
||||
['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
["c WARNING: duplicate rule: earlier: dk(C0) + [SHIFT K_B] > dk(B0) here: "],
|
||||
["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]],
|
||||
|
||||
//6-6 dup
|
||||
[[
|
||||
|
|
@ -180,7 +172,7 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),],
|
||||
[''],
|
||||
[""],
|
||||
["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]],
|
||||
["c WARNING: duplicate rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]],
|
||||
|
||||
//6-6 amb
|
||||
[[
|
||||
|
|
@ -188,29 +180,29 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),],
|
||||
[''],
|
||||
[""],
|
||||
["c WARNING: ambiguous rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]],
|
||||
["c WARNING: ambiguous rule: earlier: dk(B0) + [CAPS K_C] > 'X' here: "]],
|
||||
|
||||
// 5-5 amb
|
||||
[[
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 1, 'RALT', 'K_F', new TextEncoder().encode('X')),],
|
||||
['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
["c WARNING: ambiguous rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "], [''],
|
||||
['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
["c WARNING: ambiguous rule: earlier: dk(C0) + [NCAPS K_B] > dk(B0) here: "], [''],
|
||||
],
|
||||
|
||||
// 5-5 dup
|
||||
[[
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),],
|
||||
['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
["c WARNING: duplicate rule: earlier: dk(B0) + [NCAPS K_B] > dk(B0) here: "],
|
||||
['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
["c WARNING: duplicate rule: earlier: dk(C0) + [NCAPS K_B] > dk(B0) here: "],
|
||||
['']],
|
||||
|
||||
// 4-2 amb
|
||||
[[
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),],
|
||||
['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '],
|
||||
['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '],
|
||||
[''],
|
||||
['']],
|
||||
|
||||
|
|
@ -218,7 +210,7 @@ describe('KmnFileWriter', function () {
|
|||
[[
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C3", 'LALT', 'K_A', 1, 1, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),],
|
||||
['c WARNING: ambiguous rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
['c WARNING: ambiguous rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
[""],
|
||||
[''],],
|
||||
|
||||
|
|
@ -226,7 +218,7 @@ describe('KmnFileWriter', function () {
|
|||
[[
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('X')),],
|
||||
['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
['c WARNING: duplicate rule: earlier: [LALT K_A] > dk(C0) here: '],
|
||||
[''],
|
||||
['']],
|
||||
|
||||
|
|
@ -234,7 +226,7 @@ describe('KmnFileWriter', function () {
|
|||
[[
|
||||
new Rule("C3", 'LALT', 'K_A', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C2", '', '', 0, 0, 'LALT', 'K_A', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),],
|
||||
['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '],
|
||||
['c WARNING: ambiguous rule: later: [LALT K_A] > dk(C0) here: '],
|
||||
[''],
|
||||
['']],
|
||||
|
||||
|
|
@ -243,7 +235,7 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),],
|
||||
[''],
|
||||
["c WARNING: duplicate rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "],
|
||||
["c WARNING: duplicate rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "],
|
||||
[''],],
|
||||
|
||||
// 6-3 amb
|
||||
|
|
@ -251,14 +243,14 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C3", 'CTRL', 'K_D', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),],
|
||||
[''],
|
||||
["c WARNING: ambiguous rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "],
|
||||
["c WARNING: ambiguous rule: earlier: dk(C0) + [CAPS K_C] > 'X' here: "],
|
||||
[''],],
|
||||
|
||||
// 2-4 amb
|
||||
[[
|
||||
new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C3", 'SHIFT', 'K_B', 0, 0, 'NCAPS', 'K_E', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),],
|
||||
['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(A0) here: '],
|
||||
['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(A0) here: '],
|
||||
[''],
|
||||
['']],
|
||||
|
||||
|
|
@ -267,7 +259,7 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 1, 1, 'RALT', 'K_F', new TextEncoder().encode('Y')),],
|
||||
[''],
|
||||
['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(C0) here: '],
|
||||
['c WARNING: ambiguous rule: earlier: [SHIFT K_B] > dk(C0) here: '],
|
||||
['']],
|
||||
|
||||
// 2-2 dup
|
||||
|
|
@ -275,7 +267,7 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),
|
||||
new Rule("C2", '', '', 0, 0, 'SHIFT', 'K_B', 0, 0, 'RALT', 'K_F', new TextEncoder().encode('Y')),],
|
||||
[''],
|
||||
['c WARNING: duplicate rule: earlier: [SHIFT K_B] > dk(C0) here: '],
|
||||
['c WARNING: duplicate rule: earlier: [SHIFT K_B] > dk(C0) here: '],
|
||||
['']],
|
||||
|
||||
// 3-3 dup
|
||||
|
|
@ -284,7 +276,7 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X')),],
|
||||
[''],
|
||||
[''],
|
||||
["c WARNING: duplicate rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]],
|
||||
["c WARNING: duplicate rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]],
|
||||
|
||||
// 3-3 amb
|
||||
[[
|
||||
|
|
@ -292,7 +284,7 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C2", '', '', 0, 0, 'NCAPS', 'K_E', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y')),],
|
||||
[''],
|
||||
[''],
|
||||
["c WARNING: ambiguous rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]],
|
||||
["c WARNING: ambiguous rule: earlier: dk(A0) + [CAPS K_C] > 'X' here: "]],
|
||||
|
||||
// 2-1 amb
|
||||
[[
|
||||
|
|
@ -300,7 +292,7 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'RALT', 'K_B', new TextEncoder().encode('Y'))],
|
||||
[''],
|
||||
[''],
|
||||
['c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) here: ']],
|
||||
['c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) here: ']],
|
||||
|
||||
// 1-1 amb
|
||||
[[
|
||||
|
|
@ -308,7 +300,7 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('Y'))],
|
||||
[''],
|
||||
[''],
|
||||
["c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'X' here: "]],
|
||||
["c WARNING: ambiguous rule: earlier: [CAPS K_C] > 'X' here: "]],
|
||||
|
||||
// 1-1 amb
|
||||
[[
|
||||
|
|
@ -316,11 +308,11 @@ describe('KmnFileWriter', function () {
|
|||
new Rule("C0", '', '', 0, 0, '', '', 0, 0, 'CAPS', 'K_C', new TextEncoder().encode('X'))],
|
||||
[''],
|
||||
[''],
|
||||
["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]],
|
||||
["c WARNING: duplicate rule: earlier: [CAPS K_C] > 'X' here: "]],
|
||||
|
||||
].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[], 1);
|
||||
const result: string[] = sutW.unitTestEndpoints.reviewRules(values[0] as Rule[], 1).warningMessages;
|
||||
assert.equal(result[0], values[1][0]);
|
||||
assert.equal(result[1], values[2][0]);
|
||||
assert.equal(result[2], values[3][0]);
|
||||
|
|
@ -337,10 +329,10 @@ 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 ! "]],
|
||||
["c WARNING: ambiguous rule: later: [RALT K_B] > dk(A0) ambiguous rule: earlier: [RALT K_B] > 'X' PLEASE CHECK THAT RULE AS IT WILL NOT BE WRITTEN ! here: "]],
|
||||
].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);
|
||||
const result: string[] = sutW.unitTestEndpoints.reviewRules(values[0] as Rule[], 2).warningMessages;
|
||||
assert.equal(result[0], values[1][0]);
|
||||
assert.equal(result[1], values[2][0]);
|
||||
assert.equal(result[2], values[3][0]);
|
||||
|
|
@ -450,5 +442,42 @@ describe('KmnFileWriter', function () {
|
|||
});
|
||||
});
|
||||
});
|
||||
describe('writeCharacterOrUnicode and return values', function () {
|
||||
const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
|
||||
[
|
||||
["A", "A", "Msg "],
|
||||
["ሴ", "ሴ", "Msg "],
|
||||
["😀", "😀", "Msg "],
|
||||
["ẘ", "ẘ", "Msg "],
|
||||
["U+0001", "U+0001", "Msg Use of a control character "],
|
||||
["U+0061", "a", "Msg "],
|
||||
["", "U+0002", "Msg Use of a control character "],
|
||||
["ሴ", 'ሴ', "Msg "],
|
||||
["", "U+0003", "Msg Use of a control character "],
|
||||
["ሺ", "ሺ", "Msg "],
|
||||
["", "U+0006", "Msg Use of a control character "],
|
||||
['', '', 'Msg empty output or unsupported numerical html entity: '],
|
||||
].forEach(function (values) {
|
||||
it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () {
|
||||
const result = sutW.writeCharacterOrUnicode(values[0] as string, "Msg ");
|
||||
assert.isNotNull(result);
|
||||
assert.equal(result.character, values[1]);
|
||||
assert.equal(result.message, values[2]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('writeCharacterOrUnicode and return null for result.message and result.character', function () {
|
||||
const sutW = new KmnFileWriter(compilerTestCallbacks, compilerTestOptions);
|
||||
[
|
||||
[null, null],
|
||||
[undefined, null],
|
||||
|
||||
].forEach(function (values) {
|
||||
it(('should convert "' + values[0] + '"').padEnd(25, " ") + 'to "' + values[1] + '"', async function () {
|
||||
const result = sutW.writeCharacterOrUnicode(values[0], "");
|
||||
assert.isNull(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue