From fea40e2689b8f185568a2b42f6575dcae846077f Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 9 Dec 2024 11:47:54 +0000 Subject: [PATCH 01/32] chore(common/web): initial test boilerplate --- .../kmx/kmx-plus/element-string.tests.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 common/web/types/tests/kmx/kmx-plus/element-string.tests.ts diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts new file mode 100644 index 0000000000..438c16bf4a --- /dev/null +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -0,0 +1,19 @@ +/* + * Keyman is copyright (C) SIL Global. MIT License. + * + * Created by Dr Mark C. Sinclair on 2024-12-09 + * + * Test code for element-string.ts + */ + +import 'mocha'; +import { assert } from 'chai'; + +describe('Test of ElementString', () => { + describe('Test of ElemElement', () => { + describe('Test of isEqual()', () => { + assert.isTrue(true); + assert.isFalse(false); + }); + }); +}); From 13b463aedf8ef29cd1e6356662b34b6242116c49 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 9 Dec 2024 16:16:31 +0000 Subject: [PATCH 02/32] chore(common/web): add initElemElement and first true test case for isEqual() --- .../kmx/kmx-plus/element-string.tests.ts | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 438c16bf4a..2ced6327ca 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -8,12 +8,40 @@ import 'mocha'; import { assert } from 'chai'; +import { ElemElementFlags, ElemElement } from '../../../src/kmx/kmx-plus/element-string.js'; +import { StrsItem, UsetItem } from '../../../src/kmx/kmx-plus/kmx-plus.js'; +import { UnicodeSet } from '../../../src/ldml-keyboard/unicodeset-parser-api.js'; + +const GOTHIC_A = new StrsItem("𐌰", 0x10330); +const GOTHIC_A_SET = new UsetItem( + new UnicodeSet("[𐌰-𐍊]", [[0x10330,0x1034A]]), + GOTHIC_A +); describe('Test of ElementString', () => { describe('Test of ElemElement', () => { describe('Test of isEqual()', () => { - assert.isTrue(true); - assert.isFalse(false); + it('returns true when elems identical', () => { + const one = initElemElement(); + const two = initElemElement() + assert.isTrue(one.isEqual(two)); + }); }); }); }); + +function initElemElement( + value: StrsItem = GOTHIC_A, + uset: UsetItem = GOTHIC_A_SET, + order: number = 0, + tertiary: number = 1, + flags: ElemElementFlags = ElemElementFlags.none, +): ElemElement { + const ee = new ElemElement(); + ee.value = value; + ee.uset = uset; + ee.order = order; + ee.tertiary = tertiary; + ee.flags = flags; + return ee; +} From ee23da5647ad9c3b8faca036a85c94a3cae9ddef Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 16 Dec 2024 12:17:18 +0000 Subject: [PATCH 03/32] chore(common/web): add five test cases for ElemElement.isEqual() --- .../kmx/kmx-plus/element-string.tests.ts | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 2ced6327ca..f1a530efde 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -13,10 +13,16 @@ import { StrsItem, UsetItem } from '../../../src/kmx/kmx-plus/kmx-plus.js'; import { UnicodeSet } from '../../../src/ldml-keyboard/unicodeset-parser-api.js'; const GOTHIC_A = new StrsItem("𐌰", 0x10330); -const GOTHIC_A_SET = new UsetItem( +const GOTHIC_B = new StrsItem("𐌱", 0x10331); +const UGARITIC_A = new StrsItem("πŽ€", 0x10380); +const GOTHIC_SET = new UsetItem( new UnicodeSet("[𐌰-𐍊]", [[0x10330,0x1034A]]), GOTHIC_A ); +const UGARITIC_SET = new UsetItem( + new UnicodeSet("[πŽ€-𐎟]", [[0x10380,0x1039F]]), + UGARITIC_A +); describe('Test of ElementString', () => { describe('Test of ElemElement', () => { @@ -26,13 +32,38 @@ describe('Test of ElementString', () => { const two = initElemElement() assert.isTrue(one.isEqual(two)); }); + it('returns false when value differs', () => { + const one = initElemElement(GOTHIC_A); + const two = initElemElement(GOTHIC_B); + assert.isFalse(one.isEqual(two)); + }); + it('returns false when order differs', () => { + const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0); + const two = initElemElement(GOTHIC_A, GOTHIC_SET, 1); + assert.isFalse(one.isEqual(two)); + }); + it('returns false when tertiary differs', () => { + const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 1); + const two = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 2); + assert.isFalse(one.isEqual(two)); + }); + it('returns false when flags differs', () => { + const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 1, ElemElementFlags.none); + const two = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 1, ElemElementFlags.type); + assert.isFalse(one.isEqual(two)); + }); + it('returns true even though uset differs', () => { + const one = initElemElement(GOTHIC_A, GOTHIC_SET); + const two = initElemElement(GOTHIC_A, UGARITIC_SET); + assert.isTrue(one.isEqual(two)); + }); }); }); }); function initElemElement( value: StrsItem = GOTHIC_A, - uset: UsetItem = GOTHIC_A_SET, + uset: UsetItem = GOTHIC_SET, order: number = 0, tertiary: number = 1, flags: ElemElementFlags = ElemElementFlags.none, From 77076eb9ed09157b66e8159cd83078f8b705e8c3 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 16 Dec 2024 12:43:53 +0000 Subject: [PATCH 04/32] chore(common/web): add first test case for ElementString() --- .../types/tests/kmx/kmx-plus/element-string.tests.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index f1a530efde..ce3db90fc3 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -8,7 +8,7 @@ import 'mocha'; import { assert } from 'chai'; -import { ElemElementFlags, ElemElement } from '../../../src/kmx/kmx-plus/element-string.js'; +import { ElemElementFlags, ElemElement, ElementString } from '../../../src/kmx/kmx-plus/element-string.js'; import { StrsItem, UsetItem } from '../../../src/kmx/kmx-plus/kmx-plus.js'; import { UnicodeSet } from '../../../src/ldml-keyboard/unicodeset-parser-api.js'; @@ -59,6 +59,14 @@ describe('Test of ElementString', () => { }); }); }); + describe('Test of ElementString', () => { + describe('Test of fromStrings()', () => { + it('returns an empty El;ementString if source is null', () => { + const es = ElementString.fromStrings({}, null); + assert.deepEqual(es, new ElementString()); + }); + }); + }); }); function initElemElement( From 703fd2cbe6ec2be2995d0c3bb6ae8be08ac480b9 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 16 Dec 2024 15:41:00 +0000 Subject: [PATCH 05/32] chore(common/web): add use case for string array --- .../kmx/kmx-plus/element-string.tests.ts | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index ce3db90fc3..7c187d9920 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -9,11 +9,12 @@ import 'mocha'; import { assert } from 'chai'; import { ElemElementFlags, ElemElement, ElementString } from '../../../src/kmx/kmx-plus/element-string.js'; -import { StrsItem, UsetItem } from '../../../src/kmx/kmx-plus/kmx-plus.js'; +import { StrsItem, UsetItem, DependencySections, Strs } from '../../../src/kmx/kmx-plus/kmx-plus.js'; import { UnicodeSet } from '../../../src/ldml-keyboard/unicodeset-parser-api.js'; const GOTHIC_A = new StrsItem("𐌰", 0x10330); const GOTHIC_B = new StrsItem("𐌱", 0x10331); +const GOTHIC_C = new StrsItem("𐌲", 0x10332); const UGARITIC_A = new StrsItem("πŽ€", 0x10380); const GOTHIC_SET = new UsetItem( new UnicodeSet("[𐌰-𐍊]", [[0x10330,0x1034A]]), @@ -43,13 +44,13 @@ describe('Test of ElementString', () => { assert.isFalse(one.isEqual(two)); }); it('returns false when tertiary differs', () => { - const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 1); - const two = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 2); + const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 0); + const two = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 1); assert.isFalse(one.isEqual(two)); }); it('returns false when flags differs', () => { - const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 1, ElemElementFlags.none); - const two = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 1, ElemElementFlags.type); + const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 0, ElemElementFlags.none); + const two = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 0, ElemElementFlags.type); assert.isFalse(one.isEqual(two)); }); it('returns true even though uset differs', () => { @@ -61,19 +62,30 @@ describe('Test of ElementString', () => { }); describe('Test of ElementString', () => { describe('Test of fromStrings()', () => { - it('returns an empty El;ementString if source is null', () => { + it('returns an empty ElementString if source is null', () => { const es = ElementString.fromStrings({}, null); assert.deepEqual(es, new ElementString()); }); + it('can create an ElementString from a string array', () => { + const strs: Strs = new Strs(); + const sections: DependencySections = { strs: strs }; + const actual = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); + const expected = [ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + initElemElement(GOTHIC_C), + ]; + assert.deepEqual(actual, expected); + }); }); }); }); function initElemElement( value: StrsItem = GOTHIC_A, - uset: UsetItem = GOTHIC_SET, + uset: UsetItem = undefined, order: number = 0, - tertiary: number = 1, + tertiary: number = 0, flags: ElemElementFlags = ElemElementFlags.none, ): ElemElement { const ee = new ElemElement(); From 76316f1661bda4dd41f842d2eb0fd67b2be53cca Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 16 Dec 2024 17:07:52 +0000 Subject: [PATCH 06/32] chore(common/web): add test case for fromStrings() from string --- .../kmx/kmx-plus/element-string.tests.ts | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 7c187d9920..926fd8eff2 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -11,6 +11,7 @@ import { assert } from 'chai'; import { ElemElementFlags, ElemElement, ElementString } from '../../../src/kmx/kmx-plus/element-string.js'; import { StrsItem, UsetItem, DependencySections, Strs } from '../../../src/kmx/kmx-plus/kmx-plus.js'; import { UnicodeSet } from '../../../src/ldml-keyboard/unicodeset-parser-api.js'; +import { ElementParser, ElementSegment, ElementType } from '../../../src/ldml-keyboard/pattern-parser.js'; const GOTHIC_A = new StrsItem("𐌰", 0x10330); const GOTHIC_B = new StrsItem("𐌱", 0x10331); @@ -25,6 +26,8 @@ const UGARITIC_SET = new UsetItem( UGARITIC_A ); +let origElementParserSegment = ElementParser.segment; + describe('Test of ElementString', () => { describe('Test of ElemElement', () => { describe('Test of isEqual()', () => { @@ -62,6 +65,14 @@ describe('Test of ElementString', () => { }); describe('Test of ElementString', () => { describe('Test of fromStrings()', () => { + beforeEach(() => { + ElementParser.segment = (str: string): ElementSegment[] => { + return [...str].map(s => new ElementSegment(s, ElementType.codepoint)); + } + }); + afterEach(() => { + ElementParser.segment = origElementParserSegment; + }); it('returns an empty ElementString if source is null', () => { const es = ElementString.fromStrings({}, null); assert.deepEqual(es, new ElementString()); @@ -78,6 +89,17 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); }); + it('can create an ElementString from a string', () => { + const strs: Strs = new Strs(); + const sections: DependencySections = { strs: strs }; + const actual = ElementString.fromStrings(sections, "𐌰𐌱𐌲"); + const expected = [ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + initElemElement(GOTHIC_C), + ]; + assert.deepEqual(actual, expected); + }); }); }); From 09168fc083875f2d16faeb749863a2430a322a35 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 16 Dec 2024 17:38:32 +0000 Subject: [PATCH 07/32] chore(common/web): remove unneeded local variables --- .../types/tests/kmx/kmx-plus/element-string.tests.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 926fd8eff2..74207775a7 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -9,7 +9,7 @@ import 'mocha'; import { assert } from 'chai'; import { ElemElementFlags, ElemElement, ElementString } from '../../../src/kmx/kmx-plus/element-string.js'; -import { StrsItem, UsetItem, DependencySections, Strs } from '../../../src/kmx/kmx-plus/kmx-plus.js'; +import { StrsItem, UsetItem, Strs } from '../../../src/kmx/kmx-plus/kmx-plus.js'; import { UnicodeSet } from '../../../src/ldml-keyboard/unicodeset-parser-api.js'; import { ElementParser, ElementSegment, ElementType } from '../../../src/ldml-keyboard/pattern-parser.js'; @@ -78,9 +78,7 @@ describe('Test of ElementString', () => { assert.deepEqual(es, new ElementString()); }); it('can create an ElementString from a string array', () => { - const strs: Strs = new Strs(); - const sections: DependencySections = { strs: strs }; - const actual = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); + const actual = ElementString.fromStrings({ strs: new Strs() }, ["𐌰", "𐌱", "𐌲"]); const expected = [ initElemElement(GOTHIC_A), initElemElement(GOTHIC_B), @@ -90,9 +88,7 @@ describe('Test of ElementString', () => { }); }); it('can create an ElementString from a string', () => { - const strs: Strs = new Strs(); - const sections: DependencySections = { strs: strs }; - const actual = ElementString.fromStrings(sections, "𐌰𐌱𐌲"); + const actual = ElementString.fromStrings({ strs: new Strs() }, "𐌰𐌱𐌲"); const expected = [ initElemElement(GOTHIC_A), initElemElement(GOTHIC_B), From 5e4d699a7258082311d70ce34ea6df75dd97440f Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 16 Dec 2024 17:51:29 +0000 Subject: [PATCH 08/32] chore(common/web): add four test cases for order andf tertiary arguments to fromStrings() --- .../kmx/kmx-plus/element-string.tests.ts | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 74207775a7..21914a0aa0 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -96,6 +96,60 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it('can apply order string', () => { + const actual = ElementString.fromStrings( + { strs: new Strs() }, + "𐌰𐌱𐌲", + "1 2 3", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 1), + initElemElement(GOTHIC_B, undefined, 2), + initElemElement(GOTHIC_C, undefined, 3), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply single order to all', () => { + const actual = ElementString.fromStrings( + { strs: new Strs() }, + "𐌰𐌱𐌲", + "1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 1), + initElemElement(GOTHIC_B, undefined, 1), + initElemElement(GOTHIC_C, undefined, 1), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply tertiary string', () => { + const actual = ElementString.fromStrings( + { strs: new Strs() }, + "𐌰𐌱𐌲", + null, + "1 2 3", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 1), + initElemElement(GOTHIC_B, undefined, 0, 2), + initElemElement(GOTHIC_C, undefined, 0, 3), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply single tertiary to all', () => { + const actual = ElementString.fromStrings( + { strs: new Strs() }, + "𐌰𐌱𐌲", + null, + "1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 1), + initElemElement(GOTHIC_B, undefined, 0, 1), + initElemElement(GOTHIC_C, undefined, 0, 1), + ]; + assert.deepEqual(actual, expected); + }); }); }); From aef4ef41f03bbd0087951a10af2bab82253ae07c Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 16 Dec 2024 18:04:43 +0000 Subject: [PATCH 09/32] chore(common/web): add four test cases for tertiary_base and prebase arguments to fromStrings() --- .../kmx/kmx-plus/element-string.tests.ts | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 21914a0aa0..a7ab25ee7a 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -150,6 +150,68 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it('can apply tertiary_base string', () => { + const actual = ElementString.fromStrings( + { strs: new Strs() }, + "𐌰𐌱𐌲", + null, + null, + "1 0 1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.tertiary_base), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.tertiary_base), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply single tertiary_base to all', () => { + const actual = ElementString.fromStrings( + { strs: new Strs() }, + "𐌰𐌱𐌲", + null, + null, + "1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.tertiary_base), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.tertiary_base), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.tertiary_base), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply prebase string', () => { + const actual = ElementString.fromStrings( + { strs: new Strs() }, + "𐌰𐌱𐌲", + null, + null, + null, + "1 0 1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.prebase), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.prebase), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply single prebase to all', () => { + const actual = ElementString.fromStrings( + { strs: new Strs() }, + "𐌰𐌱𐌲", + null, + null, + null, + "1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.prebase), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.prebase), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.prebase), + ]; + assert.deepEqual(actual, expected); + }); }); }); From e6abbf027fce302e5923218a8d493f1e86524b4a Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 19 Dec 2024 12:00:33 +0000 Subject: [PATCH 10/32] chore(common/web): stub out strs.allocString() --- .../kmx/kmx-plus/element-string.tests.ts | 49 ++++++++++++++----- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index a7ab25ee7a..dd0aae7a9b 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -9,7 +9,7 @@ import 'mocha'; import { assert } from 'chai'; import { ElemElementFlags, ElemElement, ElementString } from '../../../src/kmx/kmx-plus/element-string.js'; -import { StrsItem, UsetItem, Strs } from '../../../src/kmx/kmx-plus/kmx-plus.js'; +import { StrsItem, UsetItem, Strs, StrsOptions, DependencySections, CharStrsItem } from '../../../src/kmx/kmx-plus/kmx-plus.js'; import { UnicodeSet } from '../../../src/ldml-keyboard/unicodeset-parser-api.js'; import { ElementParser, ElementSegment, ElementType } from '../../../src/ldml-keyboard/pattern-parser.js'; @@ -78,7 +78,9 @@ describe('Test of ElementString', () => { assert.deepEqual(es, new ElementString()); }); it('can create an ElementString from a string array', () => { - const actual = ElementString.fromStrings({ strs: new Strs() }, ["𐌰", "𐌱", "𐌲"]); + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); const expected = [ initElemElement(GOTHIC_A), initElemElement(GOTHIC_B), @@ -88,7 +90,9 @@ describe('Test of ElementString', () => { }); }); it('can create an ElementString from a string', () => { - const actual = ElementString.fromStrings({ strs: new Strs() }, "𐌰𐌱𐌲"); + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings(sections, "𐌰𐌱𐌲"); const expected = [ initElemElement(GOTHIC_A), initElemElement(GOTHIC_B), @@ -97,8 +101,10 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); it('can apply order string', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( - { strs: new Strs() }, + sections, "𐌰𐌱𐌲", "1 2 3", ); @@ -110,8 +116,10 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); it('can apply single order to all', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( - { strs: new Strs() }, + sections, "𐌰𐌱𐌲", "1", ); @@ -123,8 +131,10 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); it('can apply tertiary string', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( - { strs: new Strs() }, + sections, "𐌰𐌱𐌲", null, "1 2 3", @@ -137,8 +147,10 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); it('can apply single tertiary to all', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( - { strs: new Strs() }, + sections, "𐌰𐌱𐌲", null, "1", @@ -151,8 +163,10 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); it('can apply tertiary_base string', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( - { strs: new Strs() }, + sections, "𐌰𐌱𐌲", null, null, @@ -166,8 +180,10 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); it('can apply single tertiary_base to all', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( - { strs: new Strs() }, + sections, "𐌰𐌱𐌲", null, null, @@ -181,8 +197,10 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); it('can apply prebase string', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( - { strs: new Strs() }, + sections, "𐌰𐌱𐌲", null, null, @@ -197,8 +215,10 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); it('can apply single prebase to all', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( - { strs: new Strs() }, + sections, "𐌰𐌱𐌲", null, null, @@ -229,4 +249,9 @@ function initElemElement( ee.tertiary = tertiary; ee.flags = flags; return ee; -} +}; + +function stubStrsAllocString_Char(s?: string, opts?: StrsOptions, sections?: DependencySections): StrsItem { + return new CharStrsItem(s); +}; + From 0585b3f639af14e5e6b98555d6e74eaf42ccc78f Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 19 Dec 2024 12:13:46 +0000 Subject: [PATCH 11/32] chore(common/web): add four test cases for order etc strings that are too short --- .../kmx/kmx-plus/element-string.tests.ts | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index dd0aae7a9b..55e5f20e28 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -130,6 +130,21 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it.skip('can handle order string that is too short', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + "1 2", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 1), + initElemElement(GOTHIC_B, undefined, 2), + initElemElement(GOTHIC_C, undefined, 0), + ]; + assert.deepEqual(actual, expected); + }); it('can apply tertiary string', () => { const sections = { strs: new Strs() }; sections.strs.allocString = stubStrsAllocString_Char; @@ -162,6 +177,22 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it.skip('can handle tertiary string that is too short', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + "1 2", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 1), + initElemElement(GOTHIC_B, undefined, 0, 2), + initElemElement(GOTHIC_C, undefined, 0, 0), + ]; + assert.deepEqual(actual, expected); + }); it('can apply tertiary_base string', () => { const sections = { strs: new Strs() }; sections.strs.allocString = stubStrsAllocString_Char; @@ -196,6 +227,23 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it('can handle tertiary_base string that is too short', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + null, + "1 0", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.tertiary_base), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.none), + ]; + assert.deepEqual(actual, expected); + }); it('can apply prebase string', () => { const sections = { strs: new Strs() }; sections.strs.allocString = stubStrsAllocString_Char; @@ -232,6 +280,24 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it('can handle prebase string that is too short', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + null, + null, + "1 0", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.prebase), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.none), + ]; + assert.deepEqual(actual, expected); + }); }); }); From 1ae53a042bb8beb6f93db09e6f159120a710c2e2 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 19 Dec 2024 14:43:15 +0000 Subject: [PATCH 12/32] chore(common/web): add test cases for non-number in order and tertiary strings --- .../kmx/kmx-plus/element-string.tests.ts | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 55e5f20e28..8df97fcc29 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -145,6 +145,21 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it.skip('can handle non-number in order string', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + "1 A 3", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 1), + initElemElement(GOTHIC_B, undefined, 0), + initElemElement(GOTHIC_C, undefined, 3), + ]; + assert.deepEqual(actual, expected); + }); it('can apply tertiary string', () => { const sections = { strs: new Strs() }; sections.strs.allocString = stubStrsAllocString_Char; @@ -193,6 +208,22 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it.skip('can handle non-number in tertiary string', () => { + const sections = { strs: new Strs() }; + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + "1 A 3", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 1), + initElemElement(GOTHIC_B, undefined, 0, 0), + initElemElement(GOTHIC_C, undefined, 0, 3), + ]; + assert.deepEqual(actual, expected); + }); it('can apply tertiary_base string', () => { const sections = { strs: new Strs() }; sections.strs.allocString = stubStrsAllocString_Char; From 7694623fc9f6cf283eaa04b0801e6b6aeab2b77c Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 19 Dec 2024 16:19:21 +0000 Subject: [PATCH 13/32] chore(common/web): add first uset test case with supporting stubs and TestUnicodeSetParser class --- .../kmx/kmx-plus/element-string.tests.ts | 84 ++++++++++++++----- 1 file changed, 63 insertions(+), 21 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 8df97fcc29..b9a5987109 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -8,25 +8,36 @@ import 'mocha'; import { assert } from 'chai'; +import { constants } from '@keymanapp/ldml-keyboard-constants'; import { ElemElementFlags, ElemElement, ElementString } from '../../../src/kmx/kmx-plus/element-string.js'; -import { StrsItem, UsetItem, Strs, StrsOptions, DependencySections, CharStrsItem } from '../../../src/kmx/kmx-plus/kmx-plus.js'; -import { UnicodeSet } from '../../../src/ldml-keyboard/unicodeset-parser-api.js'; +import { StrsItem, UsetItem, Strs, StrsOptions, DependencySections, CharStrsItem, Uset } from '../../../src/kmx/kmx-plus/kmx-plus.js'; +import { UnicodeSet, UnicodeSetParser } from '../../../src/ldml-keyboard/unicodeset-parser-api.js'; import { ElementParser, ElementSegment, ElementType } from '../../../src/ldml-keyboard/pattern-parser.js'; const GOTHIC_A = new StrsItem("𐌰", 0x10330); const GOTHIC_B = new StrsItem("𐌱", 0x10331); const GOTHIC_C = new StrsItem("𐌲", 0x10332); -const UGARITIC_A = new StrsItem("πŽ€", 0x10380); -const GOTHIC_SET = new UsetItem( - new UnicodeSet("[𐌰-𐍊]", [[0x10330,0x1034A]]), - GOTHIC_A +const GOTHIC_PATTERN = "[𐌰-𐍊]"; +const GOTHIC_STRSITEM = new StrsItem(GOTHIC_PATTERN); +const GOTHIC_USETITEM = new UsetItem( + new UnicodeSet(GOTHIC_PATTERN, [[0x10330,0x1034A]]), + GOTHIC_STRSITEM ); -const UGARITIC_SET = new UsetItem( - new UnicodeSet("[πŽ€-𐎟]", [[0x10380,0x1039F]]), - UGARITIC_A +const UGARITIC_PATTERN = "[πŽ€-𐎟]"; +const UGARITIC_STRSITEM = new StrsItem(UGARITIC_PATTERN); +const UGARITIC_USETITEM = new UsetItem( + new UnicodeSet(UGARITIC_PATTERN, [[0x10380,0x1039F]]), + UGARITIC_STRSITEM ); -let origElementParserSegment = ElementParser.segment; +class TestUnicodeSetParser implements UnicodeSetParser { + parseUnicodeSet = (pattern: string, rangeCount: number) : UnicodeSet | null => { + return new UnicodeSet("[𐌰-𐍊]", [[0x10330,0x1034A]]); + }; + sizeUnicodeSet = (pattern: string) : number => { return 1; } +}; + +const origElementParserSegment = ElementParser.segment; describe('Test of ElementString', () => { describe('Test of ElemElement', () => { @@ -42,23 +53,23 @@ describe('Test of ElementString', () => { assert.isFalse(one.isEqual(two)); }); it('returns false when order differs', () => { - const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0); - const two = initElemElement(GOTHIC_A, GOTHIC_SET, 1); + const one = initElemElement(GOTHIC_A, GOTHIC_USETITEM, 0); + const two = initElemElement(GOTHIC_A, GOTHIC_USETITEM, 1); assert.isFalse(one.isEqual(two)); }); it('returns false when tertiary differs', () => { - const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 0); - const two = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 1); + const one = initElemElement(GOTHIC_A, GOTHIC_USETITEM, 0, 0); + const two = initElemElement(GOTHIC_A, GOTHIC_USETITEM, 0, 1); assert.isFalse(one.isEqual(two)); }); it('returns false when flags differs', () => { - const one = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 0, ElemElementFlags.none); - const two = initElemElement(GOTHIC_A, GOTHIC_SET, 0, 0, ElemElementFlags.type); + const one = initElemElement(GOTHIC_A, GOTHIC_USETITEM, 0, 0, ElemElementFlags.none); + const two = initElemElement(GOTHIC_A, GOTHIC_USETITEM, 0, 0, ElemElementFlags.type); assert.isFalse(one.isEqual(two)); }); it('returns true even though uset differs', () => { - const one = initElemElement(GOTHIC_A, GOTHIC_SET); - const two = initElemElement(GOTHIC_A, UGARITIC_SET); + const one = initElemElement(GOTHIC_A, GOTHIC_USETITEM); + const two = initElemElement(GOTHIC_A, UGARITIC_USETITEM); assert.isTrue(one.isEqual(two)); }); }); @@ -66,9 +77,7 @@ describe('Test of ElementString', () => { describe('Test of ElementString', () => { describe('Test of fromStrings()', () => { beforeEach(() => { - ElementParser.segment = (str: string): ElementSegment[] => { - return [...str].map(s => new ElementSegment(s, ElementType.codepoint)); - } + ElementParser.segment = stubElementParserSegment_CodePoint; }); afterEach(() => { ElementParser.segment = origElementParserSegment; @@ -329,6 +338,27 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it('can create an ElementString from a uset string', () => { + ElementParser.segment = origElementParserSegment; + const sections = { + strs: new Strs(), + uset: new Uset(), + usetparser: new TestUnicodeSetParser(), + }; + sections.strs.allocString = stubStrsAllocString_Str; + sections.uset.allocUset = stubUsetAllocUset; + const actual = ElementString.fromStrings(sections, "[𐌰-𐍊]"); + const expected = [ + initElemElement( + new StrsItem(''), + GOTHIC_USETITEM, + 0, + 0, + constants.elem_flags_type_uset, + ), + ]; + assert.deepEqual(actual, expected); + }); }); }); @@ -352,3 +382,15 @@ function stubStrsAllocString_Char(s?: string, opts?: StrsOptions, sections?: Dep return new CharStrsItem(s); }; +function stubStrsAllocString_Str(s?: string, opts?: StrsOptions, sections?: DependencySections): StrsItem { + return new StrsItem(s); +}; + +function stubElementParserSegment_CodePoint(str: string): ElementSegment[] { + return [...str].map(s => new ElementSegment(s, ElementType.codepoint)); +}; + +function stubUsetAllocUset(set: UnicodeSet, sections: DependencySections) : UsetItem { + return new UsetItem(set, new StrsItem(set.pattern)); +}; + From 9569ef208c13cbd42688b420c534fc4db743ccb6 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 19 Dec 2024 17:11:15 +0000 Subject: [PATCH 14/32] chore(common/web): corrected nesting error, and moved more code into fixtures --- .../kmx/kmx-plus/element-string.tests.ts | 525 +++++++++--------- 1 file changed, 252 insertions(+), 273 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index b9a5987109..e5702ff072 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -19,25 +19,20 @@ const GOTHIC_B = new StrsItem("𐌱", 0x10331); const GOTHIC_C = new StrsItem("𐌲", 0x10332); const GOTHIC_PATTERN = "[𐌰-𐍊]"; const GOTHIC_STRSITEM = new StrsItem(GOTHIC_PATTERN); -const GOTHIC_USETITEM = new UsetItem( - new UnicodeSet(GOTHIC_PATTERN, [[0x10330,0x1034A]]), - GOTHIC_STRSITEM -); +const GOTHIC_SET = new UnicodeSet(GOTHIC_PATTERN, [[0x10330,0x1034A]]); +const GOTHIC_USETITEM = new UsetItem(GOTHIC_SET, GOTHIC_STRSITEM); const UGARITIC_PATTERN = "[πŽ€-𐎟]"; const UGARITIC_STRSITEM = new StrsItem(UGARITIC_PATTERN); -const UGARITIC_USETITEM = new UsetItem( - new UnicodeSet(UGARITIC_PATTERN, [[0x10380,0x1039F]]), - UGARITIC_STRSITEM -); +const UGARITIC_SET = new UnicodeSet(UGARITIC_PATTERN, [[0x10380,0x1039F]]); +const UGARITIC_USETITEM = new UsetItem(UGARITIC_SET, UGARITIC_STRSITEM); class TestUnicodeSetParser implements UnicodeSetParser { - parseUnicodeSet = (pattern: string, rangeCount: number) : UnicodeSet | null => { - return new UnicodeSet("[𐌰-𐍊]", [[0x10330,0x1034A]]); - }; + parseUnicodeSet = (pattern: string, rangeCount: number) : UnicodeSet | null => { return GOTHIC_SET; }; sizeUnicodeSet = (pattern: string) : number => { return 1; } }; const origElementParserSegment = ElementParser.segment; +let sections: DependencySections = null; describe('Test of ElementString', () => { describe('Test of ElemElement', () => { @@ -77,6 +72,11 @@ describe('Test of ElementString', () => { describe('Test of ElementString', () => { describe('Test of fromStrings()', () => { beforeEach(() => { + sections = { + strs: new Strs(), + uset: new Uset(), + usetparser: new TestUnicodeSetParser(), + }; ElementParser.segment = stubElementParserSegment_CodePoint; }); afterEach(() => { @@ -87,7 +87,6 @@ describe('Test of ElementString', () => { assert.deepEqual(es, new ElementString()); }); it('can create an ElementString from a string array', () => { - const sections = { strs: new Strs() }; sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); const expected = [ @@ -97,267 +96,247 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); - }); - it('can create an ElementString from a string', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings(sections, "𐌰𐌱𐌲"); - const expected = [ - initElemElement(GOTHIC_A), - initElemElement(GOTHIC_B), - initElemElement(GOTHIC_C), - ]; - assert.deepEqual(actual, expected); - }); - it('can apply order string', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - "1 2 3", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 1), - initElemElement(GOTHIC_B, undefined, 2), - initElemElement(GOTHIC_C, undefined, 3), - ]; - assert.deepEqual(actual, expected); - }); - it('can apply single order to all', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - "1", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 1), - initElemElement(GOTHIC_B, undefined, 1), - initElemElement(GOTHIC_C, undefined, 1), - ]; - assert.deepEqual(actual, expected); - }); - it.skip('can handle order string that is too short', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - "1 2", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 1), - initElemElement(GOTHIC_B, undefined, 2), - initElemElement(GOTHIC_C, undefined, 0), - ]; - assert.deepEqual(actual, expected); - }); - it.skip('can handle non-number in order string', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - "1 A 3", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 1), - initElemElement(GOTHIC_B, undefined, 0), - initElemElement(GOTHIC_C, undefined, 3), - ]; - assert.deepEqual(actual, expected); - }); - it('can apply tertiary string', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - "1 2 3", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 1), - initElemElement(GOTHIC_B, undefined, 0, 2), - initElemElement(GOTHIC_C, undefined, 0, 3), - ]; - assert.deepEqual(actual, expected); - }); - it('can apply single tertiary to all', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - "1", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 1), - initElemElement(GOTHIC_B, undefined, 0, 1), - initElemElement(GOTHIC_C, undefined, 0, 1), - ]; - assert.deepEqual(actual, expected); - }); - it.skip('can handle tertiary string that is too short', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - "1 2", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 1), - initElemElement(GOTHIC_B, undefined, 0, 2), - initElemElement(GOTHIC_C, undefined, 0, 0), - ]; - assert.deepEqual(actual, expected); - }); - it.skip('can handle non-number in tertiary string', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - "1 A 3", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 1), - initElemElement(GOTHIC_B, undefined, 0, 0), - initElemElement(GOTHIC_C, undefined, 0, 3), - ]; - assert.deepEqual(actual, expected); - }); - it('can apply tertiary_base string', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - null, - "1 0 1", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.tertiary_base), - initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), - initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.tertiary_base), - ]; - assert.deepEqual(actual, expected); - }); - it('can apply single tertiary_base to all', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - null, - "1", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.tertiary_base), - initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.tertiary_base), - initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.tertiary_base), - ]; - assert.deepEqual(actual, expected); - }); - it('can handle tertiary_base string that is too short', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - null, - "1 0", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.tertiary_base), - initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), - initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.none), - ]; - assert.deepEqual(actual, expected); - }); - it('can apply prebase string', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - null, - null, - "1 0 1", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.prebase), - initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), - initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.prebase), - ]; - assert.deepEqual(actual, expected); - }); - it('can apply single prebase to all', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - null, - null, - "1", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.prebase), - initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.prebase), - initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.prebase), - ]; - assert.deepEqual(actual, expected); - }); - it('can handle prebase string that is too short', () => { - const sections = { strs: new Strs() }; - sections.strs.allocString = stubStrsAllocString_Char; - const actual = ElementString.fromStrings( - sections, - "𐌰𐌱𐌲", - null, - null, - null, - "1 0", - ); - const expected = [ - initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.prebase), - initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), - initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.none), - ]; - assert.deepEqual(actual, expected); - }); - it('can create an ElementString from a uset string', () => { - ElementParser.segment = origElementParserSegment; - const sections = { - strs: new Strs(), - uset: new Uset(), - usetparser: new TestUnicodeSetParser(), - }; - sections.strs.allocString = stubStrsAllocString_Str; - sections.uset.allocUset = stubUsetAllocUset; - const actual = ElementString.fromStrings(sections, "[𐌰-𐍊]"); - const expected = [ - initElemElement( - new StrsItem(''), - GOTHIC_USETITEM, - 0, - 0, - constants.elem_flags_type_uset, - ), - ]; - assert.deepEqual(actual, expected); + it('can create an ElementString from a string', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings(sections, "𐌰𐌱𐌲"); + const expected = [ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + initElemElement(GOTHIC_C), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply order string', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + "1 2 3", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 1), + initElemElement(GOTHIC_B, undefined, 2), + initElemElement(GOTHIC_C, undefined, 3), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply single order to all', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + "1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 1), + initElemElement(GOTHIC_B, undefined, 1), + initElemElement(GOTHIC_C, undefined, 1), + ]; + assert.deepEqual(actual, expected); + }); + it.skip('can handle order string that is too short', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + "1 2", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 1), + initElemElement(GOTHIC_B, undefined, 2), + initElemElement(GOTHIC_C, undefined, 0), + ]; + assert.deepEqual(actual, expected); + }); + it.skip('can handle non-number in order string', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + "1 A 3", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 1), + initElemElement(GOTHIC_B, undefined, 0), + initElemElement(GOTHIC_C, undefined, 3), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply tertiary string', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + "1 2 3", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 1), + initElemElement(GOTHIC_B, undefined, 0, 2), + initElemElement(GOTHIC_C, undefined, 0, 3), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply single tertiary to all', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + "1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 1), + initElemElement(GOTHIC_B, undefined, 0, 1), + initElemElement(GOTHIC_C, undefined, 0, 1), + ]; + assert.deepEqual(actual, expected); + }); + it.skip('can handle tertiary string that is too short', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + "1 2", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 1), + initElemElement(GOTHIC_B, undefined, 0, 2), + initElemElement(GOTHIC_C, undefined, 0, 0), + ]; + assert.deepEqual(actual, expected); + }); + it.skip('can handle non-number in tertiary string', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + "1 A 3", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 1), + initElemElement(GOTHIC_B, undefined, 0, 0), + initElemElement(GOTHIC_C, undefined, 0, 3), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply tertiary_base string', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + null, + "1 0 1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.tertiary_base), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.tertiary_base), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply single tertiary_base to all', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + null, + "1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.tertiary_base), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.tertiary_base), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.tertiary_base), + ]; + assert.deepEqual(actual, expected); + }); + it('can handle tertiary_base string that is too short', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + null, + "1 0", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.tertiary_base), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.none), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply prebase string', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + null, + null, + "1 0 1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.prebase), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.prebase), + ]; + assert.deepEqual(actual, expected); + }); + it('can apply single prebase to all', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + null, + null, + "1", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.prebase), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.prebase), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.prebase), + ]; + assert.deepEqual(actual, expected); + }); + it('can handle prebase string that is too short', () => { + sections.strs.allocString = stubStrsAllocString_Char; + const actual = ElementString.fromStrings( + sections, + "𐌰𐌱𐌲", + null, + null, + null, + "1 0", + ); + const expected = [ + initElemElement(GOTHIC_A, undefined, 0, 0, ElemElementFlags.prebase), + initElemElement(GOTHIC_B, undefined, 0, 0, ElemElementFlags.none), + initElemElement(GOTHIC_C, undefined, 0, 0, ElemElementFlags.none), + ]; + assert.deepEqual(actual, expected); + }); + it('can create an ElementString from a uset string', () => { + ElementParser.segment = origElementParserSegment; + sections.strs.allocString = stubStrsAllocString_Str; + sections.uset.allocUset = stubUsetAllocUset; + const actual = ElementString.fromStrings(sections, "[𐌰-𐍊]"); + const expected = [ + initElemElement( + new StrsItem(''), + GOTHIC_USETITEM, + 0, + 0, + constants.elem_flags_type_uset, + ), + ]; + assert.deepEqual(actual, expected); + }); }); }); }); From 58e5f0fe94c6f5d1bc0bc6369d82884514ae6fb8 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 19 Dec 2024 17:21:05 +0000 Subject: [PATCH 15/32] chore(common/web): stub the ElementParser.segment for uset --- common/web/types/tests/kmx/kmx-plus/element-string.tests.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index e5702ff072..62350510ea 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -322,7 +322,7 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); it('can create an ElementString from a uset string', () => { - ElementParser.segment = origElementParserSegment; + ElementParser.segment = stubElementParserSegment_Uset; sections.strs.allocString = stubStrsAllocString_Str; sections.uset.allocUset = stubUsetAllocUset; const actual = ElementString.fromStrings(sections, "[𐌰-𐍊]"); @@ -369,6 +369,10 @@ function stubElementParserSegment_CodePoint(str: string): ElementSegment[] { return [...str].map(s => new ElementSegment(s, ElementType.codepoint)); }; +function stubElementParserSegment_Uset(str: string): ElementSegment[] { + return [new ElementSegment(str, ElementType.uset)]; +}; + function stubUsetAllocUset(set: UnicodeSet, sections: DependencySections) : UsetItem { return new UsetItem(set, new StrsItem(set.pattern)); }; From e169ece9a374a2f2ae25b26bada64a103acd3872 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 19 Dec 2024 17:32:42 +0000 Subject: [PATCH 16/32] chore(common/web): add two test cases for uset parse failures --- .../tests/kmx/kmx-plus/element-string.tests.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 62350510ea..de18758578 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -27,8 +27,8 @@ const UGARITIC_SET = new UnicodeSet(UGARITIC_PATTERN, [[0x10380,0x1039F]]); const UGARITIC_USETITEM = new UsetItem(UGARITIC_SET, UGARITIC_STRSITEM); class TestUnicodeSetParser implements UnicodeSetParser { - parseUnicodeSet = (pattern: string, rangeCount: number) : UnicodeSet | null => { return GOTHIC_SET; }; - sizeUnicodeSet = (pattern: string) : number => { return 1; } + parseUnicodeSet = (pattern: string, rangeCount: number) : UnicodeSet | null => GOTHIC_SET; + sizeUnicodeSet = (pattern: string) : number => 1; }; const origElementParserSegment = ElementParser.segment; @@ -337,6 +337,16 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it('returns null for an invalid unicode set size', () => { + ElementParser.segment = stubElementParserSegment_Uset; + sections.usetparser.sizeUnicodeSet = (pattern: string) : number => -1; + assert.isNull(ElementString.fromStrings(sections, "[𐌰-𐍊]")); + }); + it('returns null if it cannot parse the unicode set', () => { + ElementParser.segment = stubElementParserSegment_Uset; + sections.usetparser.parseUnicodeSet = (pattern: string, rangeCount: number) : UnicodeSet | null => null; + assert.isNull(ElementString.fromStrings(sections, "[𐌰-𐍊]")); + }); }); }); }); From 80d2f498246d3274e338d6f43c9c15d518f12916 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 6 Jan 2025 15:50:07 +0000 Subject: [PATCH 17/32] chore(common/web): add test case for quad string in ElementString.fromStrings() --- .../tests/kmx/kmx-plus/element-string.tests.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index de18758578..3e53146989 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -17,6 +17,8 @@ import { ElementParser, ElementSegment, ElementType } from '../../../src/ldml-ke const GOTHIC_A = new StrsItem("𐌰", 0x10330); const GOTHIC_B = new StrsItem("𐌱", 0x10331); const GOTHIC_C = new StrsItem("𐌲", 0x10332); +const HI_GOTHIC_A = new StrsItem('\ud800', 0xd800); +const LO_GOTHIC_A = new StrsItem('\udf30', 0xdf30); const GOTHIC_PATTERN = "[𐌰-𐍊]"; const GOTHIC_STRSITEM = new StrsItem(GOTHIC_PATTERN); const GOTHIC_SET = new UnicodeSet(GOTHIC_PATTERN, [[0x10330,0x1034A]]); @@ -347,6 +349,16 @@ describe('Test of ElementString', () => { sections.usetparser.parseUnicodeSet = (pattern: string, rangeCount: number) : UnicodeSet | null => null; assert.isNull(ElementString.fromStrings(sections, "[𐌰-𐍊]")); }); + it('can handle quad strings', () => { + sections.strs.allocString = stubStrsAllocString_Char; + ElementParser.segment = stubElementParserSegment_Escaped; + const actual = ElementString.fromStrings(sections, "\\ud800\\udf30"); + const expected = [ + initElemElement(HI_GOTHIC_A), + initElemElement(LO_GOTHIC_A), + ]; + assert.deepEqual(actual, expected); + }); }); }); }); @@ -383,6 +395,11 @@ function stubElementParserSegment_Uset(str: string): ElementSegment[] { return [new ElementSegment(str, ElementType.uset)]; }; +function stubElementParserSegment_Escaped(str: string): ElementSegment[] { + const strs = str.match(/\\u[0-9a-fA-F]{4}/g); + return strs.map((s) => new ElementSegment(s, ElementType.escaped)); +}; + function stubUsetAllocUset(set: UnicodeSet, sections: DependencySections) : UsetItem { return new UsetItem(set, new StrsItem(set.pattern)); }; From c615f82db2d2dfcc817d03ad9ce34ba1fbb6ba32 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 6 Jan 2025 16:41:36 +0000 Subject: [PATCH 18/32] chore(common/web): add test cases for ElemElement.isEqual() and ElementStrings.isEqual() --- .../kmx/kmx-plus/element-string.tests.ts | 40 +++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 3e53146989..db3fdcc535 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -41,7 +41,12 @@ describe('Test of ElementString', () => { describe('Test of isEqual()', () => { it('returns true when elems identical', () => { const one = initElemElement(); - const two = initElemElement() + const two = initElemElement(); + assert.isTrue(one.isEqual(two)); + }); + it.skip('returns true when elems are clones', () => { + const one = initElemElement(new StrsItem("𐌰", 0x10330)); + const two = initElemElement(new StrsItem("𐌰", 0x10330)); assert.isTrue(one.isEqual(two)); }); it('returns false when value differs', () => { @@ -72,18 +77,18 @@ describe('Test of ElementString', () => { }); }); describe('Test of ElementString', () => { + beforeEach(() => { + sections = { + strs: new Strs(), + uset: new Uset(), + usetparser: new TestUnicodeSetParser(), + }; + ElementParser.segment = stubElementParserSegment_CodePoint; + }); + afterEach(() => { + ElementParser.segment = origElementParserSegment; + }); describe('Test of fromStrings()', () => { - beforeEach(() => { - sections = { - strs: new Strs(), - uset: new Uset(), - usetparser: new TestUnicodeSetParser(), - }; - ElementParser.segment = stubElementParserSegment_CodePoint; - }); - afterEach(() => { - ElementParser.segment = origElementParserSegment; - }); it('returns an empty ElementString if source is null', () => { const es = ElementString.fromStrings({}, null); assert.deepEqual(es, new ElementString()); @@ -360,6 +365,17 @@ describe('Test of ElementString', () => { assert.deepEqual(actual, expected); }); }); + describe('Test of isEqual()', () => { + it('returns true when ElementStrings are identical', () => { + const es = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); + assert.isTrue(es.isEqual(es)); + }); + it.skip('returns true when ElementStrings are clones', () => { + const one = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); + const two = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); + assert.isTrue(one.isEqual(two)); + }); + }); }); }); From 704486ae2e91c7d2cf8aafd3198aa18c630bd241 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 9 Jan 2025 11:27:52 +0000 Subject: [PATCH 19/32] chore(common/web): add two more test cases for ElementString.isEqual() --- .../types/tests/kmx/kmx-plus/element-string.tests.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index db3fdcc535..5c8f5ce80b 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -375,6 +375,16 @@ describe('Test of ElementString', () => { const two = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); assert.isTrue(one.isEqual(two)); }); + it('returns false when ElementStrings are different lengths', () => { + const one = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); + const two = ElementString.fromStrings(sections, ["𐌰", "𐌱"]); + assert.isFalse(one.isEqual(two)); + }); + it('returns false when ElementStrings have different ElemElements', () => { + const one = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); + const two = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌳"]); + assert.isFalse(one.isEqual(two)); + }); }); }); }); From 86095d4b11493d038c794235118f67bec13803de Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 9 Jan 2025 12:03:51 +0000 Subject: [PATCH 20/32] chore(common/web): add test case for string ElemElement --- .../tests/kmx/kmx-plus/element-string.tests.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 5c8f5ce80b..3d20c7ea3d 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -364,6 +364,20 @@ describe('Test of ElementString', () => { ]; assert.deepEqual(actual, expected); }); + it('can handle ElemElement of string type', () => { + sections.strs.allocString = stubStrsAllocString_Str; + const actual = ElementString.fromStrings(sections, ["𐌰𐌱𐌲",]); + const expected = [ + initElemElement( + new StrsItem("𐌰𐌱𐌲"), + undefined, + 0, + 0, + constants.elem_flags_type_str, + ), + ]; + assert.deepEqual(actual, expected); + }); }); describe('Test of isEqual()', () => { it('returns true when ElementStrings are identical', () => { From 23b3de14d91ebfe19445cf2d3b8e1f3a6220fe6f Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 9 Jan 2025 12:08:15 +0000 Subject: [PATCH 21/32] chore(common/web): clarify describe strings --- common/web/types/tests/kmx/kmx-plus/element-string.tests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 3d20c7ea3d..6c6f8b8ec9 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -36,7 +36,7 @@ class TestUnicodeSetParser implements UnicodeSetParser { const origElementParserSegment = ElementParser.segment; let sections: DependencySections = null; -describe('Test of ElementString', () => { +describe('Test of ElementString file', () => { describe('Test of ElemElement', () => { describe('Test of isEqual()', () => { it('returns true when elems identical', () => { @@ -76,7 +76,7 @@ describe('Test of ElementString', () => { }); }); }); - describe('Test of ElementString', () => { + describe('Test of ElementString class', () => { beforeEach(() => { sections = { strs: new Strs(), From 9d555a0639c24cb12a76863426b788063f04b367 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 9 Jan 2025 14:12:56 +0000 Subject: [PATCH 22/32] chore(common/web): introduce initElementString() to remove dependency on fromStrings() in isEqual() tests --- .../kmx/kmx-plus/element-string.tests.ts | 48 ++++++++++++++++--- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 6c6f8b8ec9..054bb3d393 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -17,6 +17,7 @@ import { ElementParser, ElementSegment, ElementType } from '../../../src/ldml-ke const GOTHIC_A = new StrsItem("𐌰", 0x10330); const GOTHIC_B = new StrsItem("𐌱", 0x10331); const GOTHIC_C = new StrsItem("𐌲", 0x10332); +const GOTHIC_D = new StrsItem("𐌳", 0x10333); const HI_GOTHIC_A = new StrsItem('\ud800', 0xd800); const LO_GOTHIC_A = new StrsItem('\udf30', 0xdf30); const GOTHIC_PATTERN = "[𐌰-𐍊]"; @@ -381,22 +382,49 @@ describe('Test of ElementString file', () => { }); describe('Test of isEqual()', () => { it('returns true when ElementStrings are identical', () => { - const es = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); + const es = initElementString([ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + initElemElement(GOTHIC_C), + ]); assert.isTrue(es.isEqual(es)); }); it.skip('returns true when ElementStrings are clones', () => { - const one = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); - const two = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); + const one = initElementString([ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + initElemElement(GOTHIC_C), + ]); + const two = initElementString([ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + initElemElement(GOTHIC_C), + ]); assert.isTrue(one.isEqual(two)); }); it('returns false when ElementStrings are different lengths', () => { - const one = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); - const two = ElementString.fromStrings(sections, ["𐌰", "𐌱"]); + const one = initElementString([ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + initElemElement(GOTHIC_C), + ]); + const two = initElementString([ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + ]); assert.isFalse(one.isEqual(two)); }); it('returns false when ElementStrings have different ElemElements', () => { - const one = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌲"]); - const two = ElementString.fromStrings(sections, ["𐌰", "𐌱", "𐌳"]); + const one = initElementString([ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + initElemElement(GOTHIC_C), + ]); + const two = initElementString([ + initElemElement(GOTHIC_A), + initElemElement(GOTHIC_B), + initElemElement(GOTHIC_D), + ]); assert.isFalse(one.isEqual(two)); }); }); @@ -419,6 +447,12 @@ function initElemElement( return ee; }; +function initElementString(elemElements: ElemElement[]): ElementString { + const es: ElementString = new ElementString(); + elemElements.forEach((ee) => {es.push(ee)}); + return es; +}; + function stubStrsAllocString_Char(s?: string, opts?: StrsOptions, sections?: DependencySections): StrsItem { return new CharStrsItem(s); }; From b9c7835fbf513b4e926146e81988a9e2f2df9f35 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Thu, 9 Jan 2025 14:45:35 +0000 Subject: [PATCH 23/32] fix(common/web): add isEqual() method to StrsItem and use it in ElemElement.isEqual() --- common/web/types/src/kmx/kmx-plus/element-string.ts | 4 ++-- common/web/types/src/kmx/kmx-plus/kmx-plus.ts | 4 ++++ common/web/types/tests/kmx/kmx-plus/element-string.tests.ts | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/common/web/types/src/kmx/kmx-plus/element-string.ts b/common/web/types/src/kmx/kmx-plus/element-string.ts index b389107cce..ad3eaf6084 100644 --- a/common/web/types/src/kmx/kmx-plus/element-string.ts +++ b/common/web/types/src/kmx/kmx-plus/element-string.ts @@ -19,8 +19,8 @@ export class ElemElement { order: number; // -128 to +127; used only by reorder element values tertiary: number; // -128 to +127; used only by reorder element values flags: ElemElementFlags; - isEqual(a: ElemElement) { - return a.value === this.value && + isEqual(a: ElemElement): boolean { + return a.value.isEqual(this.value) && a.order === this.order && a.tertiary === this.tertiary && a.flags === this.flags; diff --git a/common/web/types/src/kmx/kmx-plus/kmx-plus.ts b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts index a88688f7ab..d0de2989d0 100644 --- a/common/web/types/src/kmx/kmx-plus/kmx-plus.ts +++ b/common/web/types/src/kmx/kmx-plus/kmx-plus.ts @@ -131,6 +131,10 @@ export class StrsItem { get isOneChar() { return this.char !== undefined; } + + isEqual(a: StrsItem): boolean { + return a.value === this.value && a.char === this.char; + } }; /** diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 054bb3d393..0dc21a49fe 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -45,7 +45,7 @@ describe('Test of ElementString file', () => { const two = initElemElement(); assert.isTrue(one.isEqual(two)); }); - it.skip('returns true when elems are clones', () => { + it('returns true when elems are clones', () => { const one = initElemElement(new StrsItem("𐌰", 0x10330)); const two = initElemElement(new StrsItem("𐌰", 0x10330)); assert.isTrue(one.isEqual(two)); @@ -389,7 +389,7 @@ describe('Test of ElementString file', () => { ]); assert.isTrue(es.isEqual(es)); }); - it.skip('returns true when ElementStrings are clones', () => { + it('returns true when ElementStrings are clones', () => { const one = initElementString([ initElemElement(GOTHIC_A), initElemElement(GOTHIC_B), From a279767accf20966288b6bca746ac78548c6bc70 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 13 Jan 2025 11:37:58 +0000 Subject: [PATCH 24/32] fix(common/web): add ElementString.parseIntOrZero() method to handle invalid order and tertiary params --- common/web/types/src/kmx/kmx-plus/element-string.ts | 8 ++++++-- .../web/types/tests/kmx/kmx-plus/element-string.tests.ts | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/common/web/types/src/kmx/kmx-plus/element-string.ts b/common/web/types/src/kmx/kmx-plus/element-string.ts index b389107cce..2b4321abda 100644 --- a/common/web/types/src/kmx/kmx-plus/element-string.ts +++ b/common/web/types/src/kmx/kmx-plus/element-string.ts @@ -104,8 +104,8 @@ export class ElementString extends Array { typeFlag |= constants.elem_flags_type_str; } } - elem.order = orders.length ? parseInt(orders[i], 10) : 0; - elem.tertiary = tertiaries.length ? parseInt(tertiaries[i], 10) : 0; + elem.order = orders.length ? this.parseIntOrZero(orders[i]) : 0; + elem.tertiary = tertiaries.length ? this.parseIntOrZero(tertiaries[i]) : 0; elem.flags = ElemElementFlags.none | (ElemElementFlags.type & typeFlag) | (tertiary_bases?.[i] == '1' /* TODO-LDML: or 'true'? */ ? ElemElementFlags.tertiary_base : 0) | @@ -125,5 +125,9 @@ export class ElementString extends Array { } return true; } + private static parseIntOrZero(str: string) { + const num = parseInt(str, 10); + return !Number.isNaN(num) ? num : 0; + } } ; diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index 054bb3d393..be8b56da2d 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -142,7 +142,7 @@ describe('Test of ElementString file', () => { ]; assert.deepEqual(actual, expected); }); - it.skip('can handle order string that is too short', () => { + it('can handle order string that is too short', () => { sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( sections, @@ -156,7 +156,7 @@ describe('Test of ElementString file', () => { ]; assert.deepEqual(actual, expected); }); - it.skip('can handle non-number in order string', () => { + it('can handle non-number in order string', () => { sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( sections, @@ -200,7 +200,7 @@ describe('Test of ElementString file', () => { ]; assert.deepEqual(actual, expected); }); - it.skip('can handle tertiary string that is too short', () => { + it('can handle tertiary string that is too short', () => { sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( sections, @@ -215,7 +215,7 @@ describe('Test of ElementString file', () => { ]; assert.deepEqual(actual, expected); }); - it.skip('can handle non-number in tertiary string', () => { + it('can handle non-number in tertiary string', () => { sections.strs.allocString = stubStrsAllocString_Char; const actual = ElementString.fromStrings( sections, From d48ccda140f1c011af1b5f4edc9889d2e5266ea6 Mon Sep 17 00:00:00 2001 From: "Dr Mark C. Sinclair" Date: Mon, 13 Jan 2025 12:05:39 +0000 Subject: [PATCH 25/32] fix(common/web): add test cases for parseIntOrZero() --- .../types/src/kmx/kmx-plus/element-string.ts | 2 +- .../tests/kmx/kmx-plus/element-string.tests.ts | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/common/web/types/src/kmx/kmx-plus/element-string.ts b/common/web/types/src/kmx/kmx-plus/element-string.ts index 2b4321abda..7a65592c0b 100644 --- a/common/web/types/src/kmx/kmx-plus/element-string.ts +++ b/common/web/types/src/kmx/kmx-plus/element-string.ts @@ -125,7 +125,7 @@ export class ElementString extends Array { } return true; } - private static parseIntOrZero(str: string) { + private static parseIntOrZero(str: string): number { const num = parseInt(str, 10); return !Number.isNaN(num) ? num : 0; } diff --git a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts index be8b56da2d..5f5b53481b 100644 --- a/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts +++ b/common/web/types/tests/kmx/kmx-plus/element-string.tests.ts @@ -428,6 +428,24 @@ describe('Test of ElementString file', () => { assert.isFalse(one.isEqual(two)); }); }); + describe('Test of parseIntOrZero()', () => { + it('returns a number for a valid string', () => { + const num = ElementString['parseIntOrZero']('1'); + assert.equal(num, 1); + }); + it('returns zero for an invalid string', () => { + const num = ElementString['parseIntOrZero']('A'); + assert.equal(num, 0); + }); + it('returns zero for undefined', () => { + const num = ElementString['parseIntOrZero'](undefined); + assert.equal(num, 0); + }); + it('returns zero for a null string', () => { + const num = ElementString['parseIntOrZero'](null); + assert.equal(num, 0); + }); + }); }); }); From 4f4df94bb30a9920eab30ef6d67c7da22aaa3db8 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 16 Jan 2025 16:29:53 +0100 Subject: [PATCH 26/32] chore(linux): Update debian changelog (cherry picked from commit fdafd5879ec926b1f71a768f61fe17e71749602b) --- linux/debian/changelog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/linux/debian/changelog b/linux/debian/changelog index 3a2dae55f3..22fd40caad 100644 --- a/linux/debian/changelog +++ b/linux/debian/changelog @@ -1,3 +1,9 @@ +keyman (17.0.333-1) unstable; urgency=medium + + * New upstream release. + + -- Eberhard Beilharz Thu, 16 Jan 2025 16:29:44 +0100 + keyman (17.0.332-1) unstable; urgency=medium * set environment variable for rendering of downloads dialog (#12617) From 43e958b5d04eae7df47e91b0097133b1a95b6562 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 16 Jan 2025 16:46:12 +0100 Subject: [PATCH 27/32] chore(linux): update copyright year --- linux/debian/copyright | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/linux/debian/copyright b/linux/debian/copyright index 3956e1463d..46f156e19b 100644 --- a/linux/debian/copyright +++ b/linux/debian/copyright @@ -4,24 +4,24 @@ Upstream-Contact: Keyman team Source: https://github.com/keymanapp/keyman Files: * -Copyright: 2018-2024 SIL Global +Copyright: 2018-2025 SIL Global License: MIT Files: linux/ibus-keyman/* -Copyright: 2004-2024 SIL Global +Copyright: 2004-2025 SIL Global License: GPL-2+ Files: linux/ibus-keyman/src/keymanutil.c linux/ibus-keyman/src/keymanutil.h linux/ibus-keyman/src/kmpdetails.c linux/ibus-keyman/src/kmpdetails.h -Copyright: 2009-2024 SIL Global +Copyright: 2009-2025 SIL Global License: GPL-2+ or MIT Files: linux/ibus-keyman/src/keyman-service.c linux/ibus-keyman/src/keyman-service.h linux/keyman-config/buildtools/help2md -Copyright: 2018-2024 SIL Global +Copyright: 2018-2025 SIL Global License: GPL-3+ Files: linux/ibus-keyman/tests/ibusimcontext.c @@ -31,7 +31,7 @@ Copyright: 2008-2010, Peng Huang 2008-2013, Peng Huang 2008-2021, Red Hat, Inc. 2015-2021, Takao Fujiwara - 2021-2024, SIL Global + 2021-2025, SIL Global License: LGPL-2.1+ Files: linux/keyman-config/buildtools/help2man @@ -41,7 +41,7 @@ License: GPL-3+ Files: debian/com.keyman.config.appdata.xml debian/com.keyman.ibus_keyman.metainfo.xml Copyright: 2019 Daniel Glassey - 2022-2024 SIL Global + 2022-2025 SIL Global License: MIT License: MIT From c0bfb541face0266cf64c07ae156dd121df93c0b Mon Sep 17 00:00:00 2001 From: Darcy Wong Date: Fri, 17 Jan 2025 10:28:32 +0700 Subject: [PATCH 28/32] chore(common): Add 17.0.333 to version history --- HISTORY.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 78352f95e5..7f830394da 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -953,7 +953,7 @@ ## 18.0.41 alpha 2024-05-22 * fix(developer): handle `KM_CORE_IT_INVALIDATE_CONTEXT` in debugger (#11488) -* chore(linux): Trigger GHA packaging for stable builds :cherries: (#11495) +* chore(linux): Trigger GHA packaging for stable builds (#11495) * chore(android,mac,windows): Update crowdin strings for DE (#11497) * feat(web): custom infrastructure for @web/test-runner use (#11403) * chore(web): conversion of lm-worker browser-test for @web/test-runner use (#11404) @@ -1149,6 +1149,17 @@ * chore(common): move to 18.0 alpha (#10713) * chore: move to 18.0 alpha +## 17.0.333 stable 2025-01-16 + +* fix(core): permanently disable logging (#12674) +* fix(linux): pushing of updated changelog branch (#12819) +* fix(linux): work around Lintian errors (#12817) +* fix(core): implement ldml_processor::get_key_list() (#12816) +* chore(linux): Update debian changelog (#12022) +* fix(android): use main looper to dispatch key events when OSK is hidden (#12875) +* chore: use GitHub PR titles when writing HISTORY.md (#12908) +* fix(developer): filter incorrect fonts out of .keyboard_info (#12913) + ## 17.0.332 stable 2024-11-06 * fix(developer): create Server config directory before options save (#12609) From b4ca7cb8c69bcf5d4ec66b6406b9ca2d963d1ffc Mon Sep 17 00:00:00 2001 From: Joshua Horton Date: Fri, 17 Jan 2025 15:29:47 +0700 Subject: [PATCH 29/32] fix(web): patches up unit test with execution dependent on autocorrect state --- .../interfaces/prediction/predictionContext.tests.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.tests.js b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.tests.js index 4217aeb69b..9aa9cd8015 100644 --- a/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.tests.js +++ b/web/src/test/auto/headless/engine/interfaces/prediction/predictionContext.tests.js @@ -161,15 +161,21 @@ describe("PredictionContext", () => { assert.equal(updateFake.callCount, 3); suggestions = updateFake.thirdCall.args[0]; + // Note: this unit test was originally written with auto-correct on! + // #11941 was written 2024-07-25 (added unit test for auto-correction method) + // #12169 was written 2024-08-14, which is what added THIS unit test. + // This does re-use the apply-revert oriented mocking. // Should skip the (second) "apple", "apply", "apps" round, as it became outdated // by its following request before its response could be received. - assert.deepEqual(suggestions.map((obj) => obj.displayAs), ['β€œapple”', 'applied']); - assert.equal(suggestions.find((obj) => obj.tag == 'keep').displayAs, 'β€œapple”'); + assert.deepEqual(suggestions.map((obj) => obj.displayAs), ['applied']); // 'β€œapple”' included with auto-correct enabled. + // Is not displayed; we only display it if auto-correct is on, as 'applied' would be automatic then. + assert.equal(predictiveContext.keepSuggestion.displayAs, 'β€œapple”'); + // assert.equal(suggestions.find((obj) => obj.tag == 'keep').displayAs, 'β€œapple”'); // with auto-correct enabled. assert.equal(suggestions.find((obj) => obj.transform.deleteLeft != 0).displayAs, 'applied'); // Our reused mocking doesn't directly provide the 'keep' suggestion; we // need to remove it before testing for set equality. - assert.deepEqual(suggestions.splice(1), expected); + assert.deepEqual(suggestions /*.splice(1)*/, expected); }); it('sendUpdateState retrieves the most recent suggestion set', async function() { From 1ed44014d96a7b9c3bf8354ff46d6000194aef7f Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Fri, 17 Jan 2025 13:01:57 -0500 Subject: [PATCH 30/32] auto: increment master version to 18.0.171 --- HISTORY.md | 7 +++++++ VERSION.md | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 78352f95e5..2940491b3a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,12 @@ # Keyman Version History +## 18.0.170 alpha 2025-01-17 + +* chore(linux): update copyright year (#12918) +* fix(web): patch unit test with execution dependent on autocorrect state (#12940) +* test(common/web): unit tests for element-string (#12811) +* chore(linux): Update debian changelog (#12917) + ## 18.0.169 alpha 2025-01-17 * chore(windows): remove `postinstall` state from mermaid diagram (#12923) diff --git a/VERSION.md b/VERSION.md index df7920cb67..d4aee009e5 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.170 \ No newline at end of file +18.0.171 \ No newline at end of file From 548866e1a519539b7fd5299ebd6d0b86dc3759fe Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Sat, 18 Jan 2025 13:01:28 -0500 Subject: [PATCH 31/32] auto: increment master version to 18.0.172 --- HISTORY.md | 5 +++++ VERSION.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 2940491b3a..6d02a97e26 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,10 @@ # Keyman Version History +## 18.0.171 alpha 2025-01-18 + +* fix(common/web): add StrsItem.isEqual() method (#12868) +* fix(common/web): handle invalid order and tertiary arguments to ElementString.fromString() (#12882) + ## 18.0.170 alpha 2025-01-17 * chore(linux): update copyright year (#12918) diff --git a/VERSION.md b/VERSION.md index d4aee009e5..02da667937 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.171 \ No newline at end of file +18.0.172 \ No newline at end of file From 5c1a15591adf28dfb3ec2b94195e20460a4fe575 Mon Sep 17 00:00:00 2001 From: Keyman Build Agent Date: Sun, 19 Jan 2025 13:01:08 -0500 Subject: [PATCH 32/32] auto: increment master version to 18.0.173 --- HISTORY.md | 4 ++++ VERSION.md | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 71c44403a8..be484aee8b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Keyman Version History +## 18.0.172 alpha 2025-01-19 + +* chore(common): Add 17.0.333 to version history (#12926) + ## 18.0.171 alpha 2025-01-18 * fix(common/web): add StrsItem.isEqual() method (#12868) diff --git a/VERSION.md b/VERSION.md index 02da667937..5f77e86146 100644 --- a/VERSION.md +++ b/VERSION.md @@ -1 +1 @@ -18.0.172 \ No newline at end of file +18.0.173 \ No newline at end of file