Merge pull request #7187 from keymanapp/feat/core/ldml-add-meta-version

feat(core): add version field to meta 🙀
This commit is contained in:
Marc Durdin 2022-09-07 11:27:20 +10:00 committed by GitHub
commit 423debfef7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 89 additions and 49 deletions

View file

@ -21,7 +21,7 @@
#define LDML_LENGTH_KEYS_ITEM 0x10
#define LDML_LENGTH_LOCA 0x10
#define LDML_LENGTH_LOCA_ITEM 0x4
#define LDML_LENGTH_META 0x24
#define LDML_LENGTH_META 0x28
#define LDML_LENGTH_SECT 0x10
#define LDML_LENGTH_SECT_ITEM 0x8
#define LDML_LENGTH_STRS 0x10

View file

@ -80,7 +80,7 @@ export const constants: Constants = {
/**
* length of the 'meta' section
*/
length_meta: 36,
length_meta: 40,
/**
* bitwise or value for fallback=omit in meta.settings
*/

View file

@ -34,6 +34,11 @@ namespace kmx {
#pragma warning ( disable : 4200 )
#endif
/**
* Indicates an offset into the strs table (0 = zero length)
*/
typedef KMX_DWORD KMXPLUS_STR;
struct COMP_KMXPLUS_HEADER {
KMX_DWORD ident; // 0000 Section name
KMX_DWORD size; // 0004 Section length
@ -105,12 +110,13 @@ static_assert(sizeof(struct COMP_KMXPLUS_STRS) == LDML_LENGTH_STRS, "mismatched
struct COMP_KMXPLUS_META {
static const KMX_DWORD IDENT = LDML_SECTIONID_META;
COMP_KMXPLUS_HEADER header;
KMX_DWORD name;
KMX_DWORD author;
KMX_DWORD conform;
KMX_DWORD layout;
KMX_DWORD normalization;
KMX_DWORD indicator;
KMXPLUS_STR name;
KMXPLUS_STR author;
KMXPLUS_STR conform;
KMXPLUS_STR layout;
KMXPLUS_STR normalization;
KMXPLUS_STR indicator;
KMXPLUS_STR version;
KMX_DWORD settings;
/**
* @brief True if section is valid.
@ -121,7 +127,7 @@ struct COMP_KMXPLUS_META {
static_assert(sizeof(struct COMP_KMXPLUS_META) == LDML_LENGTH_META, "mismatched size of section meta");
struct COMP_KMXPLUS_LOCA_ENTRY {
KMX_DWORD locale; // 0010+ locale string entry
KMXPLUS_STR locale; // 0010+ locale string entry
};
struct COMP_KMXPLUS_LOCA {
@ -142,7 +148,7 @@ static_assert(sizeof(struct COMP_KMXPLUS_LOCA) == LDML_LENGTH_LOCA, "mismatched
struct COMP_KMXPLUS_KEYS_ENTRY {
KMX_DWORD vkey;
KMX_DWORD mod;
KMX_DWORD to;
KMX_DWORD to; // to may be KMXPLUS_STR or UTF32 char
KMX_DWORD flags;
};

View file

@ -23,6 +23,7 @@
"commander": "^3.0.0",
"crc-32": "^1.2.2",
"restructure": "^3.0.0",
"semver": "^7.3.7",
"typescript": "^4.5.4",
"xml2js": "^0.4.19"
},
@ -39,8 +40,9 @@
},
"mocha": {
"spec": "build/test/**/test-*.js",
"require": ["source-map-support/register"]
"require": [
"source-map-support/register"
]
},
"repository": {
"type": "git",

View file

@ -3,6 +3,7 @@ import { KeyboardSettings, Meta, Meta_NormalizationForm } from "../kmx/kmx-plus"
import { isValidEnumValue } from "../util/util";
import { CompilerErrors } from "./errors";
import { SectionCompiler } from "./section-compiler";
import * as semver from "semver";
export class MetaCompiler extends SectionCompiler {
@ -13,17 +14,33 @@ export class MetaCompiler extends SectionCompiler {
public validate(): boolean {
let valid = true;
const normalization = this.keyboard.info?.normalization;
if(normalization !== undefined) {
if(!isValidEnumValue(Meta_NormalizationForm, normalization)) {
this.callbacks.reportMessage(CompilerErrors.InvalidNormalization({form: normalization}));
valid = false;
}
}
valid &&= this.validateNormalization(this.keyboard.info?.normalization);
valid &&= this.validateVersion(this.keyboard.version?.number);
return valid;
}
private validateVersion(versionNumber?: string) {
if(versionNumber !== undefined) {
if(versionNumber.match(/^[=v]/i)) {
// semver ignores a preceding '=' or 'v'
return false;
}
return !!semver.parse(versionNumber, {loose: false, includePrerelease: true});
}
return true;
}
private validateNormalization(normalization?: string) {
if (normalization !== undefined) {
if (!isValidEnumValue(Meta_NormalizationForm, normalization)) {
this.callbacks.reportMessage(CompilerErrors.InvalidNormalization({ form: normalization }));
return false;
}
}
return true;
}
public compile(): Meta {
let result = new Meta();
result.name = this.keyboard.names?.name?.[0]?.value;
@ -32,6 +49,7 @@ export class MetaCompiler extends SectionCompiler {
result.layout = this.keyboard.info?.layout;
result.normalization = this.keyboard.info?.normalization as Meta_NormalizationForm;
result.indicator = this.keyboard.info?.indicator;
result.version = this.keyboard.version?.number ?? "0";
result.settings =
(this.keyboard.settings?.fallback == "omit" ? KeyboardSettings.fallback : 0) |
(this.keyboard.settings?.transformFailure == "omit" ? KeyboardSettings.transformFailure : 0) |

View file

@ -41,6 +41,7 @@ interface BUILDER_META extends BUILDER_SECTION {
layout: number; //str
normalization: number; //str
indicator: number; //str
version: number; //str
settings: number; //bitfield
};
@ -100,7 +101,7 @@ export default class KMXPlusBuilder {
}
}
let idx = this.sect_strs.items.findIndex(v => v._value == value);
let idx = this.sect_strs.items.findIndex(v => v._value === value);
if(idx >= 0) {
return idx;
}
@ -147,6 +148,7 @@ export default class KMXPlusBuilder {
layout: this.alloc_string(this.file.kmxplus.meta.layout),
normalization: this.alloc_string(this.file.kmxplus.meta.normalization),
indicator: this.alloc_string(this.file.kmxplus.meta.indicator),
version: this.alloc_string(this.file.kmxplus.meta.version),
settings: this.file.kmxplus.meta.settings ?? 0,
};
}

View file

@ -25,6 +25,7 @@ export class Meta extends Section {
layout: string;
normalization: Meta_NormalizationForm;
indicator: string;
version: string; // semver version string, defaults to "0"
settings: KeyboardSettings;
};
@ -133,6 +134,7 @@ export default class KMXPlusFile extends KMXFile {
layout: r.uint32le, //str
normalization: r.uint32le, //str
indicator: r.uint32le, //str
version: r.uint32le, //str
settings: r.uint32le, //new r.Bitfield(r.uint32le, ['fallback', 'transformFailure', 'transformPartial'])
});

View file

@ -19,6 +19,7 @@ export interface LKKeyboard {
conformsTo?: string;
locales?: LKLocales;
version?: LKVersion;
info?: LKInfo;
names?: LKNames;
settings?: LKSettings;
@ -34,6 +35,10 @@ export interface LKLocale {
id?: string;
};
export interface LKVersion {
number: string; // semver string
}
export interface LKInfo {
author?: string;
indicator?: string;

View file

@ -3,7 +3,7 @@ block(kmxheader) # struct COMP_KEYBOARD {
00 10 00 00 # KMX_DWORD dwFileVersion; // 0004 Version of the file - Keyman 4.0 is 0x0400
fc 29 af f8 # KMX_DWORD dwCheckSum; // 0008 As stored in keyboard
13 06 7c 19 # KMX_DWORD dwCheckSum; // 0008 As stored in keyboard
00 00 00 00 # KMX_DWORD KeyboardID; // 000C as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts
01 00 00 00 # KMX_DWORD IsRegistered; // 0010
00 00 00 00 # KMX_DWORD version; // 0014 keyboard version
@ -53,7 +53,7 @@ block(sect) # struct COMP_KMXPLUS_SECT {
block(strs) # struct COMP_KMXPLUS_STRS {
73 74 72 73 # KMX_DWORD header.ident; // 0000 Section name - strs
diff(strs,endstrs) # KMX_DWORD header.size; // 0004 Section length
09 00 00 00 # KMX_DWORD count; // 0008 count of str entries
0A 00 00 00 # KMX_DWORD count; // 0008 count of str entries
00 00 00 00 # KMX_DWORD reserved; // 000C padding
# Next sections are string entries
@ -66,6 +66,7 @@ block(strs) # struct COMP_KMXPLUS_STRS {
diff(strs,strLayout) sizeof(strLayout,2)
diff(strs,strNorm) sizeof(strNorm,2)
diff(strs,strIndicator) sizeof(strIndicator,2)
diff(strs,strVersion) sizeof(strVersion,2)
diff(strs,strLocale) sizeof(strLocale,2)
diff(strs,strKey1) sizeof(strKey1,2)
diff(strs,strKey2) sizeof(strKey2,2)
@ -81,6 +82,7 @@ block(strConformsTo) 74 00 65 00 63 00 68 00 70 00 72 00 65 00 76 00
block(strLayout) 71 00 77 00 65 00 72 00 74 00 79 00 block(x) 00 00 # 3:qwerty
block(strNorm) 4e 00 46 00 43 00 block(x) 00 00 # 4:NFC
block(strIndicator) 3d d8 40 de block(x) 00 00 # 5:🙀
block(strVersion) 30 00 block(x) 00 00 # 6:0
block(strLocale) 6d 00 74 00 block(x) 00 00 # 7:mt
block(strKey1) 27 01 block(x) 00 00 # 8:ħ
block(strKey2) 90 17 b6 17 block(x) 00 00 # 9:ថា
@ -96,6 +98,7 @@ block(meta) # struct COMP_KMXPLUS_META {
03 00 00 00 # KMX_DWORD layout;
04 00 00 00 # KMX_DWORD normalization;
05 00 00 00 # KMX_DWORD indicator;
06 00 00 00 # KMX_DWORD version;
00 00 00 00 # KMX_DWORD settings;
# };
@ -104,7 +107,7 @@ block(loca) # struct COMP_KMXPLUS_LOCA {
sizeof(loca) # KMX_DWORD header.size; // 0004 Section length
01 00 00 00 # KMX_DWORD count; // 0008 number of locales
00 00 00 00 # KMX_DWORD reserved;
06 00 00 00 # KMX_DWORD locale; // 0010+ locale string entry = 'mt'
07 00 00 00 # KMX_DWORD locale; // 0010+ locale string entry = 'mt'
# };
block(keys) # struct COMP_KMXPLUS_KEYS {
@ -116,7 +119,7 @@ block(keys) # struct COMP_KMXPLUS_KEYS {
# Keys data:
c0 00 00 00 00 00 00 00 07 00 00 00 01 00 00 00 # KMX_DWORD vkey, mod, to, flags;
31 00 00 00 00 00 00 00 08 00 00 00 01 00 00 00 # KMX_DWORD vkey, mod, to, flags;
c0 00 00 00 00 00 00 00 08 00 00 00 01 00 00 00 # KMX_DWORD vkey, mod, to, flags;
31 00 00 00 00 00 00 00 09 00 00 00 01 00 00 00 # KMX_DWORD vkey, mod, to, flags;
block(eof) # end of file

50
package-lock.json generated
View file

@ -477,6 +477,7 @@
"commander": "^3.0.0",
"crc-32": "^1.2.2",
"restructure": "^3.0.0",
"semver": "^7.3.7",
"typescript": "^4.5.4",
"xml2js": "^0.4.19"
},
@ -4561,12 +4562,14 @@
"integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0="
},
"node_modules/lru-cache": {
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==",
"devOptional": true,
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=12"
"node": ">=10"
}
},
"node_modules/macos-release": {
@ -5867,18 +5870,17 @@
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"node_modules/semver": {
"version": "7.3.6",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
"devOptional": true,
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"dependencies": {
"lru-cache": "^7.4.0"
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0"
"node": ">=10"
}
},
"node_modules/send": {
@ -6884,8 +6886,7 @@
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"optional": true
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/yaml": {
"version": "1.10.2",
@ -7814,6 +7815,7 @@
"crc-32": "^1.2.2",
"mocha": "^8.4.0",
"restructure": "^3.0.0",
"semver": "*",
"ts-node": "^9.1.1",
"typescript": "^4.5.4",
"xml2js": "^0.4.19"
@ -11003,10 +11005,12 @@
"integrity": "sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0="
},
"lru-cache": {
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.8.1.tgz",
"integrity": "sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg==",
"devOptional": true
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"requires": {
"yallist": "^4.0.0"
}
},
"macos-release": {
"version": "2.5.0",
@ -11986,12 +11990,11 @@
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"semver": {
"version": "7.3.6",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz",
"integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==",
"devOptional": true,
"version": "7.3.7",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
"integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
"requires": {
"lru-cache": "^7.4.0"
"lru-cache": "^6.0.0"
}
},
"send": {
@ -12756,8 +12759,7 @@
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"optional": true
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"yaml": {
"version": "1.10.2",