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

This commit is contained in:
SabineSIL 2026-06-04 17:32:29 +02:00 committed by GitHub
commit 78e4e32ef8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 36 additions and 30 deletions

View file

@ -7,7 +7,7 @@ import { CompilerErrorNamespace, CompilerErrorSeverity, CompilerMessageSpec as m
const Namespace = CompilerErrorNamespace.Converter;
//const SevInfo = CompilerErrorSeverity.Info | Namespace;
// const SevHint = CompilerErrorSeverity.Hint | Namespace;
const SevHint = CompilerErrorSeverity.Hint | Namespace;
const SevWarn = CompilerErrorSeverity.Warn | Namespace;
const SevError = CompilerErrorSeverity.Error | Namespace;
// const SevFatal = CompilerErrorSeverity.Fatal | Namespace;
@ -82,5 +82,10 @@ export class ConverterMessages {
this.WARN_EmptyOutput,
`Key has empty output (possibly caused by use of html entity) at keyMap index ${def(o.keymapIndex)} on Keycode ${def(o.key)} (${def(o.KeyName)})`
);
static HINT_EmptyOutput = SevHint | 0x000E;
static Hint_EmptyOutput =(o: { keymapIndex: string, key: string, KeyName: string; }) => m(
this.HINT_EmptyOutput,
`Key has empty output at keyMap index ${def(o.keymapIndex)} on Keycode ${def(o.key)} (${def(o.KeyName)}) possibly caused by use of html entity `
);
}

View file

@ -234,18 +234,7 @@ export class KeylayoutToKmnConverter {
// ...............e. g. <key code="1" output="s"/> ...............................................................................
// ...............................................................................................................................
if (jsonObj.keyboard.keyMapSet[0].keyMap[i].key[j]['output'] === "") {
/* this.callbacks.reportMessage(ConverterMessages.Warn_EmptyOutput({
keymapIndex: jsonObj.keyboard.keyMapSet[0].keyMap[i]['index'],
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;*/
console.log('Empty output');
}
else 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++) {

View file

@ -96,14 +96,15 @@ export class KmnFileWriter {
// (e.g. when in a keylayout file the same modifiers occur in several behaviors thus producing the same rules).
// This is to filter out those duplicate Rule objects
const uniqueDataRules: Rule[] = dataUkelele.rules.filter((curr) => {
return (!(curr.output.length === 0 || curr.output === undefined)
return (!(curr.output === undefined)
&& (curr.key !== "")
&& ((curr.ruleType === "C0")
|| (curr.ruleType === "C1")
|| (curr.ruleType === "C2" && (curr.deadkey !== ""))
|| (curr.ruleType === "C3" && (curr.deadkey !== "") && (curr.prevDeadkey !== "")))
);
}).reduce<Rule[]>((unique, o) => {
}).reduce((unique, o) => {
if (!unique.some((obj: Rule) =>
new TextDecoder().decode(obj.output) === new TextDecoder().decode(o.output)
@ -1619,10 +1620,12 @@ export class KmnFileWriter {
*/
public writeCharacterOrUnicode(ctr: string, msg: string = ""): MessageCharacter {
if ((ctr === null) || (ctr === undefined) || (ctr.length === 0)) {
return { character: '', message: '' };
if ((ctr === null) || (ctr === undefined)) {
return null;
}
let msg_control = '';
let msg_entity = '';
let versionOutputCharacter;
const out: MessageCharacter = {
message: msg,
@ -1644,6 +1647,10 @@ export class KmnFileWriter {
: KeylayoutToKmnConverter.MAX_CTRL_CHARACTER
);
if (ctr.length === 0) {
msg_entity = "empty output or unsupported numerical html entity: ";
}
// 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)) {
@ -1658,17 +1665,21 @@ export class KmnFileWriter {
if (versionOutputCharacter)
out.character = versionOutputCharacter;
// add a warning message
if (msg == "") {
out.message = "c WARNING: use of a control character ";
}
else {
out.message = msg + "; Use of a control character ";
}
msg_control = "Use of a control character ";
}
else {
out.character = this.convertToUnicodeCharacter(ctr) ?? "";
}
// add a warning message
if (msg !== "") {
msg = msg + msg_control + msg_entity;
}
if ((msg === "") && (msg_entity !== "" || msg_control !== "")) {
msg = "c WARNING: " + msg_entity + msg_control;
}
out.message = msg;
return out;
}

View file

@ -42,6 +42,7 @@ describe('KeylayoutToKmnConverter', function () {
['../data/Test_ambiguous_keys.keylayout'],
['../data/Test_differentEncodings.keylayout'],
['../data/Test_ExtraWarning.keylayout'],
['../data/Test_characters.keylayout'],
].forEach(function (files) {
it(files + " should give no errors ", async function () {
await sut.run(makePathToFixture(files[0]));
@ -61,10 +62,11 @@ describe('KeylayoutToKmnConverter', function () {
sut.run(makePathToFixture(files[0]));
// assert.isTrue(compilerTestCallbacks.messages.length === 1 && compilerTestCallbacks.messages[0].code === 5292037);
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);
[
@ -79,7 +81,6 @@ describe('KeylayoutToKmnConverter', function () {
['../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 () {
await sut.run(makePathToFixture(files[0]));
@ -95,7 +96,7 @@ describe('KeylayoutToKmnConverter', function () {
['../data/Test_undefinedAction.keylayout'],
].forEach(function (files) {
it(files + " should give Error: undefined action detected", async function () {
await sut.run(makePathToFixture(files[0]));
sut.run(makePathToFixture(files[0]));
assert.equal(compilerTestCallbacks.messages.length, 1);
assert.equal(compilerTestCallbacks.messages[0].code, 5292040);
});