Skip to content

Commit

Permalink
Merge branch 'master' into fix/mac/12582-sync-osk-with-keyboard
Browse files Browse the repository at this point in the history
  • Loading branch information
sgschantz authored Dec 16, 2024
2 parents fcb3d4c + faf2a5b commit 6026302
Show file tree
Hide file tree
Showing 84 changed files with 1,678 additions and 248 deletions.
24 changes: 24 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Keyman Version History

## 18.0.159 alpha 2024-12-13

* chore(core): remove meson warnings for wasm builds (#12827)
* chore(linux): Update debian changelog (#12023)

## 18.0.158 alpha 2024-12-11

* fix(linux): pushing of updated changelog branch (#12818)
* fix(linux): work around Lintian errors (#12815)

## 18.0.157 alpha 2024-12-10

* test(common/web): unit tests for kvk-file-writer (#12734)

## 18.0.156 alpha 2024-12-09

* fix(developer): remove platforms from kmc-generate LM readme (#12803)
* test(developer): add test for ERROR_DescriptionIsMissing to kmc-keyboard-info (#12804)
* chore(developer): verify bundled node version when building installer (#12806)
* fix(developer): support hint property in displaymap (#12807)
* fix(common/web): delete replaceExtension in types/src/util/file-types.ts (#12762)
* chore(developer): add some docs for language examples in kmp.json (#12805)
* fix(core): implement ldml_processor::get_key_list() (#12644)

## 18.0.155 alpha 2024-12-07

* chore(android,windows): Update crowdin for Czech (#12792)
Expand Down
2 changes: 1 addition & 1 deletion VERSION.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.0.156
18.0.160
16 changes: 0 additions & 16 deletions common/web/types/src/util/file-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,19 +166,3 @@ export function filenameIs(filename: string, fileType: Source | Binary) {
}
return filename.toLowerCase().endsWith(fileType);
}

/**
* Replaces a filename extension with the new extension. Returns `null` if the
* filename does not end with oldExtension.
* @param filename
* @param oldExtension
* @param newExtension
* @returns
*/
export function replaceExtension(filename: string, oldExtension: string, newExtension: string): string {
const ext = filename.substring(filename.length - oldExtension.length);
if(ext !== oldExtension) {
return null;
}
return filename.substring(0, filename.length - oldExtension.length) + newExtension;
}
325 changes: 325 additions & 0 deletions common/web/types/tests/kvk/kvk-file-writer.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,325 @@
/*
* Keyman is copyright (C) SIL Global. MIT License.
*
* Created by Dr Mark C. Sinclair on 2024-12-05
*
* Test code for kvk-file-writer.ts
*/

import 'mocha';
import { assert } from 'chai';
import { KvkFileWriter } from '../../src/main.js';
import { VisualKeyboard,
VisualKeyboardKey,
VisualKeyboardFont,
DEFAULT_KVK_FONT
} from '../../src/kvk/visual-keyboard.js';
import { BUILDER_KVK_FILE,
BUILDER_KVK_HEADER_FLAGS,
BUILDER_KVK_STRING,
BUILDER_KVK_HEADER_IDENTIFIER,
BUILDER_KVK_HEADER_VERSION,
BUILDER_KVK_KEY,
BUILDER_KVK_KEY_FLAGS,
BUILDER_KVK_SHIFT_STATE,
} from '../../src/kvk/kvk-file.js';

const VISUAL_KEYBOARD_TEXT_COLOR = 0xFF000008;

describe('Test of KVK-File-Writer', () => {
describe('Test of write()', () => {
it('can create a visual keyboard', () => {
const writer = new KvkFileWriter;
const vk = initVisualKeyboard([
initVisualKeyboardKey(0),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
]);
const file = writer.write(vk);
assert.isNotNull(file);
});
});
describe('Test of build()', () => {
it('can build a BUILDER_KVK_FILE', () => {
const vk = initVisualKeyboard([
initVisualKeyboardKey(0),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
]);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
it('does not take account of the VisualKeyboard version', () => {
const vk_version = (BUILDER_KVK_HEADER_VERSION + 0x0100);
const vk = initVisualKeyboard([
initVisualKeyboardKey(0),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
],
vk_version,
BUILDER_KVK_HEADER_FLAGS.kvkhNone,
"associatedKeyboard",
DEFAULT_KVK_FONT,
DEFAULT_KVK_FONT,
undefined,
);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
it.skip('can handle a null associatedKeyboard', () => {
const vk_associatedKeyboard: string = null;
const vk = initVisualKeyboard([
initVisualKeyboardKey(0),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
],
undefined,
BUILDER_KVK_HEADER_FLAGS.kvkhNone,
vk_associatedKeyboard,
DEFAULT_KVK_FONT,
DEFAULT_KVK_FONT,
undefined,
);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
it.skip('can handle a null ansiFont name', () => {
const vk_ansiFont_name: string = null;
const vk = initVisualKeyboard([
initVisualKeyboardKey(0),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
],
undefined,
BUILDER_KVK_HEADER_FLAGS.kvkhNone,
"associatedKeyboard",
{ name: vk_ansiFont_name, size: -12 },
DEFAULT_KVK_FONT,
undefined,
);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
it.skip('can handle a null unicodeFont name', () => {
const vk_unicodeFont_name: string = null;
const vk = initVisualKeyboard([
initVisualKeyboardKey(0),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
],
undefined,
BUILDER_KVK_HEADER_FLAGS.kvkhNone,
"associatedKeyboard",
DEFAULT_KVK_FONT,
{ name: vk_unicodeFont_name, size: -12 },
undefined,
);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
it('can handle a null vkey', () => {
const vkk_vkey: number = null;
const vk = initVisualKeyboard([
initVisualKeyboardKey(
vkk_vkey,
BUILDER_KVK_KEY_FLAGS.kvkkBitmap,
BUILDER_KVK_SHIFT_STATE.KVKS_NORMAL,
"text",
null,
),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
]);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
it('can handle a null key flags', () => {
const vkk_flags: BUILDER_KVK_KEY_FLAGS = null;
const vk = initVisualKeyboard([
initVisualKeyboardKey(
0,
vkk_flags,
BUILDER_KVK_SHIFT_STATE.KVKS_NORMAL,
"text",
null,
),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
]);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
it('can handle a null key shift', () => {
const vkk_shift: BUILDER_KVK_SHIFT_STATE = null;
const vk = initVisualKeyboard([
initVisualKeyboardKey(
0,
BUILDER_KVK_KEY_FLAGS.kvkkBitmap,
vkk_shift,
"text",
null,
),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
]);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
it('can handle a null key text', () => {
const vkk_text: string = null;
const vk = initVisualKeyboard([
initVisualKeyboardKey(
0,
BUILDER_KVK_KEY_FLAGS.kvkkBitmap,
BUILDER_KVK_SHIFT_STATE.KVKS_NORMAL,
vkk_text,
null,
),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
]);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
it('can handle a non-null key bitmap', () => {
const vkk_bitmap: number[] = [0];
const vk = initVisualKeyboard([
initVisualKeyboardKey(
0,
BUILDER_KVK_KEY_FLAGS.kvkkBitmap,
BUILDER_KVK_SHIFT_STATE.KVKS_NORMAL,
"text",
vkk_bitmap,
),
initVisualKeyboardKey(1),
initVisualKeyboardKey(2),
]);
const writer = new KvkFileWriter;
const binary: BUILDER_KVK_FILE = writer['build'](vk);
checkBuilderKvkFile(binary, vk);
});
});
describe('Test of setString()', () => {
it('can set a BUILDER_KVK_STRING', () => {
const bks: BUILDER_KVK_STRING = { len: 0, str: null };
const writer = new KvkFileWriter;
const str = "hello";
writer['setString'](bks, str);
assert.equal(bks.len, str.length + 1);
assert.deepEqual(bks.str, str);
});
it('can handle an empty string', () => {
const bks: BUILDER_KVK_STRING = { len: 0, str: null };
const writer = new KvkFileWriter;
const str = "";
writer['setString'](bks, str);
assert.equal(bks.len, str.length + 1);
assert.deepEqual(bks.str, str);
});
it('throws TypeError for a null BUILDER_KVK_STRING', () => {
assert.throws(() => {
const writer = new KvkFileWriter;
writer['setString'](null, "");
}, TypeError);
});
it('throws TypeError for a null value', () => {
assert.throws(() => {
const bks: BUILDER_KVK_STRING = { len: 0, str: null };
const writer = new KvkFileWriter;
writer['setString'](bks, null);
}, TypeError);
});
});
});

function initVisualKeyboard(
vkks: VisualKeyboardKey[],
version: number = undefined,
flags: BUILDER_KVK_HEADER_FLAGS = BUILDER_KVK_HEADER_FLAGS.kvkhNone,
associatedKeyboard: string = "associatedKeyboard",
ansiFont: VisualKeyboardFont = DEFAULT_KVK_FONT,
unicodeFont: VisualKeyboardFont = DEFAULT_KVK_FONT,
underlyingLayout: string = undefined,
): VisualKeyboard {
const vkh = {
version: version,
flags: flags,
associatedKeyboard: associatedKeyboard,
ansiFont: ansiFont,
unicodeFont: unicodeFont,
underlyingLayout: underlyingLayout,
};
return { header: vkh, keys: vkks };
};

function initVisualKeyboardKey(
vkey: number,
flags: BUILDER_KVK_KEY_FLAGS = BUILDER_KVK_KEY_FLAGS.kvkkBitmap,
shift: BUILDER_KVK_SHIFT_STATE = BUILDER_KVK_SHIFT_STATE.KVKS_NORMAL,
text: string = "text",
bitmap: number[] = null,
): VisualKeyboardKey {
const vkk: VisualKeyboardKey = {
vkey,
flags,
shift,
text,
bitmap: bitmap ? new Uint8Array(bitmap) : null,
};
return vkk;
}

function checkBuilderKvkFile(binary: BUILDER_KVK_FILE, vk: VisualKeyboard) {
assert.equal(binary.header.identifier, BUILDER_KVK_HEADER_IDENTIFIER);
assert.equal(binary.header.version, BUILDER_KVK_HEADER_VERSION);
if (vk.header.associatedKeyboard != null) {
assert.deepEqual(binary.header.associatedKeyboard.str, vk.header.associatedKeyboard);
} else {
assert.deepEqual(binary.header.associatedKeyboard.str, '');
}
assert.equal(binary.header.flags, vk.header.flags);
assert.equal(binary.header.ansiFont.color, VISUAL_KEYBOARD_TEXT_COLOR);
assert.equal(binary.header.ansiFont.size, vk.header.ansiFont.size);
if (vk.header.ansiFont.name != null) {
assert.deepEqual(binary.header.ansiFont.name.str, vk.header.ansiFont.name);
} else {
assert.deepEqual(binary.header.ansiFont.name.str, '');
}
assert.equal(binary.header.unicodeFont.color, VISUAL_KEYBOARD_TEXT_COLOR);
assert.equal(binary.header.unicodeFont.size, vk.header.unicodeFont.size);
if (vk.header.unicodeFont.name != null) {
assert.deepEqual(binary.header.unicodeFont.name.str, vk.header.unicodeFont.name);
} else {
assert.deepEqual(binary.header.unicodeFont.name.str, '');
}
for (let idx=0; idx<binary.keys.length; idx++) {
checkBuilderKvkKey(binary.keys[idx], vk.keys[idx])
}
}

function checkBuilderKvkKey(target: BUILDER_KVK_KEY, source: VisualKeyboardKey) {
assert.equal(target.flags, source.flags);
assert.equal(target.shift, source.shift);
assert.equal(target.vkey, source.vkey);
if (source.text != null) {
assert.deepEqual(target.text.str, source.text);
} else {
assert.deepEqual(target.text.str, '');
}
if (source.bitmap != null) {
assert.equal(target.bitmapSize, source.bitmap.byteLength);
assert.deepEqual(target.bitmapData, Array.from(source.bitmap));
} else {
assert.equal(target.bitmapSize, 0);
assert.deepEqual(target.bitmapData, []);
}
}
Loading

0 comments on commit 6026302

Please sign in to comment.