From 7b6447c3e438c30eb826b685ebdcbea73486559d Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 2 Sep 2026 09:52:51 +0200 Subject: [PATCH] fix(developer): improve validation of minDeviceWidth to match spec * Hint on multiple missing minDeviceWidth * Disallow blank or whitespace minDeviceWidth value * Additional tests for minDeviceWidth Fixes: #16457 Test-bot: skip --- developer/src/kmc-ldml/src/compiler/layr.ts | 19 ++++++++---- .../src/compiler/ldml-compiler-messages.ts | 10 ++++++- .../sections/layr/error-bad-width-.xml | 22 ++++++++++++++ .../sections/layr/error-bad-width-0.xml | 2 +- .../sections/layr/error-bad-width-1024.xml | 2 +- .../sections/layr/error-bad-width-1500.xml | 2 +- .../sections/layr/error-bad-width-x.xml | 2 +- ...e-touch-forms-without-min-device-width.xml | 29 +++++++++++++++++++ ...ple-forms-one-without-min-device-width.xml | 29 +++++++++++++++++++ developer/src/kmc-ldml/test/layr.tests.ts | 11 ++++++- 10 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-.xml create mode 100644 developer/src/kmc-ldml/test/fixtures/sections/layr/hint-multiple-touch-forms-without-min-device-width.xml create mode 100644 developer/src/kmc-ldml/test/fixtures/sections/layr/multiple-forms-one-without-min-device-width.xml diff --git a/developer/src/kmc-ldml/src/compiler/layr.ts b/developer/src/kmc-ldml/src/compiler/layr.ts index f260d4f2aa..822ea961b2 100644 --- a/developer/src/kmc-ldml/src/compiler/layr.ts +++ b/developer/src/kmc-ldml/src/compiler/layr.ts @@ -20,19 +20,26 @@ export class LayrCompiler extends SectionCompiler { let valid = true; let totalLayerCount = 0; let hardwareLayers = 0; - let touchLayers = 0; + let touchLayerCount = 0; + let hasNullDeviceWidth = false; const deviceWidths = new Set(); this.keyboard3.layers?.forEach((layers) => { const { formId } = layers; if (formId === 'touch') { - touchLayers++; + touchLayerCount++; totalLayerCount += layers.layer?.length; - // TODO-LDML: CLDR-19754 spec does not require minDeviceWidth, but if multiple touch forms then it would be important for differentiation const { minDeviceWidth } = layers; - if (!minDeviceWidth || + if (minDeviceWidth === undefined || minDeviceWidth === null) { + if(hasNullDeviceWidth) { + this.callbacks.reportMessage(LdmlCompilerMessages.Hint_MultipleTouchFormsWithoutMinDeviceWidth(layers)); + } + hasNullDeviceWidth = true; + } else if ( + (typeof minDeviceWidth === 'string' && (minDeviceWidth).trim() === '') || + Number.isNaN(Number(minDeviceWidth)) || minDeviceWidth < constants.layr_min_minDeviceWidth || - minDeviceWidth > constants.layr_max_minDeviceWidth || - Number.isNaN(Number(minDeviceWidth))) { + minDeviceWidth > constants.layr_max_minDeviceWidth + ) { valid = false; this.callbacks.reportMessage(LdmlCompilerMessages.Error_InvalidLayerWidth({minDeviceWidth}, layers)); } else if (deviceWidths.has(minDeviceWidth)) { diff --git a/developer/src/kmc-ldml/src/compiler/ldml-compiler-messages.ts b/developer/src/kmc-ldml/src/compiler/ldml-compiler-messages.ts index 7d0ae6e308..88c92f7e21 100644 --- a/developer/src/kmc-ldml/src/compiler/ldml-compiler-messages.ts +++ b/developer/src/kmc-ldml/src/compiler/ldml-compiler-messages.ts @@ -277,7 +277,7 @@ export class LdmlCompilerMessages { ); static ERROR_InvalidLayerWidth = SevError | 0x002D; - static Error_InvalidLayerWidth = (o: { minDeviceWidth: number }, compileContext?: ObjectWithCompileContext) => mx( + static Error_InvalidLayerWidth = (o: { minDeviceWidth: number | string }, compileContext?: ObjectWithCompileContext) => mx( this.ERROR_InvalidLayerWidth, compileContext, `Invalid Layers minDeviceWidth=${def(o.minDeviceWidth)}`, `Width must be between 1-999 (millimeters), inclusive.` // sync with layr_max_minDeviceWidth / layr_max_maxDeviceWidth (from spec) @@ -328,6 +328,14 @@ export class LdmlCompilerMessages { and should not have an \`id\` attribute. `); + static HINT_MultipleTouchFormsWithoutMinDeviceWidth = SevHint | 0x0035; + static Hint_MultipleTouchFormsWithoutMinDeviceWidth = (compileContext?: ObjectWithCompileContext) => mx( + this.HINT_MultipleTouchFormsWithoutMinDeviceWidth, compileContext, + `When multiple touch forms are present, 'minDeviceWidth' is required to differentiate them`, ` + Touch forms are differentiated by their minimum device width, so when there is + more than one, at most one form may omit the \`minDeviceWidth\` attribute. + `); + // // Transform syntax errors begin at ...F00 (SevErrorTransform) diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-.xml new file mode 100644 index 0000000000..ede584dc28 --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-0.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-0.xml index 956cc28019..bd3a58112a 100644 --- a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-0.xml +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-0.xml @@ -19,7 +19,7 @@ - + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-1024.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-1024.xml index 50b22150f5..08796be62d 100644 --- a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-1024.xml +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-1024.xml @@ -19,7 +19,7 @@ - + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-1500.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-1500.xml index 87c30e9e46..2e101fdd03 100644 --- a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-1500.xml +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-1500.xml @@ -12,7 +12,7 @@ - + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-x.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-x.xml index 392cc868b4..6106e9ab42 100644 --- a/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-x.xml +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-x.xml @@ -12,7 +12,7 @@ - + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/hint-multiple-touch-forms-without-min-device-width.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/hint-multiple-touch-forms-without-min-device-width.xml new file mode 100644 index 0000000000..dbf66bece9 --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/hint-multiple-touch-forms-without-min-device-width.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/fixtures/sections/layr/multiple-forms-one-without-min-device-width.xml b/developer/src/kmc-ldml/test/fixtures/sections/layr/multiple-forms-one-without-min-device-width.xml new file mode 100644 index 0000000000..e89c59610b --- /dev/null +++ b/developer/src/kmc-ldml/test/fixtures/sections/layr/multiple-forms-one-without-min-device-width.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/developer/src/kmc-ldml/test/layr.tests.ts b/developer/src/kmc-ldml/test/layr.tests.ts index fa7a5889de..6d8918089c 100644 --- a/developer/src/kmc-ldml/test/layr.tests.ts +++ b/developer/src/kmc-ldml/test/layr.tests.ts @@ -173,7 +173,16 @@ describe('layr', function () { LdmlCompilerMessages.Error_DuplicateLayerWidth({ minDeviceWidth: 120}), ] }, - ...[0, 1024, 1500, `x` as unknown as number].map(minDeviceWidth => ({ + { + subpath: 'sections/layr/hint-multiple-touch-forms-without-min-device-width.xml', + warnings: [ + LdmlCompilerMessages.Hint_MultipleTouchFormsWithoutMinDeviceWidth(), + ] + }, + { + subpath: 'sections/layr/multiple-forms-one-without-min-device-width.xml', + }, + ...[0, 1024, 1500, `x`, ``].map(minDeviceWidth => ({ subpath: `sections/layr/error-bad-width-${minDeviceWidth}.xml`, errors: [ //