mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-09 17:17:41 +00:00
Merge pull request #16501 from keymanapp/fix/developer/16457-ldml-validate-mindevicewidth
fix(developer): improve validation of minDeviceWidth to match spec
This commit is contained in:
commit
b6f528b4ce
10 changed files with 116 additions and 12 deletions
|
|
@ -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<number>();
|
||||
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' && (<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)) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
22
developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-.xml
vendored
Normal file
22
developer/src/kmc-ldml/test/fixtures/sections/layr/error-bad-width-.xml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<keyboard3 xmlns="https://schemas.unicode.org/cldr/45/keyboard3" locale="und" conformsTo="45">
|
||||
<info name="layr-error-custom-form"/>
|
||||
<keys>
|
||||
<key id="one" output="1" />
|
||||
<key id="two" output="2" />
|
||||
<key id="three" output="3" />
|
||||
</keys>
|
||||
<layers formId="iso">
|
||||
<layer modifiers="none">
|
||||
<row keys="one two three" />
|
||||
</layer>
|
||||
</layers>
|
||||
<layers formId="touch" minDeviceWidth=""> <!-- a blank value is not permitted (instead, omit the attribute entirely) -->
|
||||
<layer id="base">
|
||||
<row keys="one" />
|
||||
<row keys="two" />
|
||||
<row keys="three" />
|
||||
</layer>
|
||||
</layers>
|
||||
</keyboard3>
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
<row keys="three" />
|
||||
</layer>
|
||||
</layers>
|
||||
<layers formId="touch" minDeviceWidth="0"> <!-- dup -->
|
||||
<layers formId="touch" minDeviceWidth="0"> <!-- width 0 not permitted -->
|
||||
<layer id="base">
|
||||
<row keys="one" />
|
||||
<row keys="two" />
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
<row keys="three" />
|
||||
</layer>
|
||||
</layers>
|
||||
<layers formId="touch" minDeviceWidth="1024"> <!-- dup -->
|
||||
<layers formId="touch" minDeviceWidth="1024"> <!-- max width 999mm -->
|
||||
<layer id="base">
|
||||
<row keys="one" />
|
||||
<row keys="two" />
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<row keys="one two three" />
|
||||
</layer>
|
||||
</layers>
|
||||
<layers formId="touch" minDeviceWidth="1500">
|
||||
<layers formId="touch" minDeviceWidth="1500"> <!-- max width 999mm -->
|
||||
<layer id="base">
|
||||
<row keys="one" />
|
||||
<row keys="two" />
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
<row keys="one two three" />
|
||||
</layer>
|
||||
</layers>
|
||||
<layers formId="touch" minDeviceWidth="x">
|
||||
<layers formId="touch" minDeviceWidth="x"> <!-- not a number -->
|
||||
<layer id="base">
|
||||
<row keys="one" />
|
||||
<row keys="two" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<keyboard3 xmlns="https://schemas.unicode.org/cldr/45/keyboard3" locale="und" conformsTo="45">
|
||||
<info name="layr-hint-multiple-touch-forms-without-min-device-width"/>
|
||||
<keys>
|
||||
<key id="one" output="1" />
|
||||
<key id="two" output="2" />
|
||||
<key id="three" output="3" />
|
||||
</keys>
|
||||
<layers formId="iso">
|
||||
<layer modifiers="none">
|
||||
<row keys="one two three" />
|
||||
</layer>
|
||||
</layers>
|
||||
<layers formId="touch">
|
||||
<layer id="base">
|
||||
<row keys="one" />
|
||||
<row keys="two" />
|
||||
<row keys="three" />
|
||||
</layer>
|
||||
</layers>
|
||||
<layers formId="touch"> <!-- two forms without minDeviceWidth -->
|
||||
<layer id="base">
|
||||
<row keys="one" />
|
||||
<row keys="two" />
|
||||
<row keys="three" />
|
||||
</layer>
|
||||
</layers>
|
||||
</keyboard3>
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<keyboard3 xmlns="https://schemas.unicode.org/cldr/45/keyboard3" locale="und" conformsTo="45">
|
||||
<info name="layr-multiple-forms-one-without-min-device-width"/>
|
||||
<keys>
|
||||
<key id="one" output="1" />
|
||||
<key id="two" output="2" />
|
||||
<key id="three" output="3" />
|
||||
</keys>
|
||||
<layers formId="iso">
|
||||
<layer modifiers="none">
|
||||
<row keys="one two three" />
|
||||
</layer>
|
||||
</layers>
|
||||
<layers formId="touch"> <!-- okay: only one form without minDeviceWidth -->
|
||||
<layer id="base">
|
||||
<row keys="one" />
|
||||
<row keys="two" />
|
||||
<row keys="three" />
|
||||
</layer>
|
||||
</layers>
|
||||
<layers formId="touch" minDeviceWidth="120">
|
||||
<layer id="base">
|
||||
<row keys="one" />
|
||||
<row keys="two" />
|
||||
<row keys="three" />
|
||||
</layer>
|
||||
</layers>
|
||||
</keyboard3>
|
||||
|
|
@ -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',
|
||||
},
|
||||
...<any>[0, 1024, 1500, `x`, ``].map(minDeviceWidth => ({
|
||||
subpath: `sections/layr/error-bad-width-${minDeviceWidth}.xml`,
|
||||
errors: [
|
||||
//
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue