Skip to content

Commit

Permalink
feat(common): ldml scancodes 🙀
Browse files Browse the repository at this point in the history
For: #9403

- use Symbols to track import status
  • Loading branch information
srl295 committed Sep 22, 2023
1 parent 6a54ebd commit 3a677da
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 6 deletions.
17 changes: 13 additions & 4 deletions common/web/types/src/ldml-keyboard/ldml-keyboard-xml-reader.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as xml2js from 'xml2js';
import { LDMLKeyboardXMLSourceFile, LKImport } from './ldml-keyboard-xml.js';
import { LDMLKeyboardXMLSourceFile, LKImport, ImportStatus } from './ldml-keyboard-xml.js';
import { default as AjvModule } from 'ajv';
const Ajv = AjvModule.default; // The actual expected Ajv type.
import { boxXmlArray } from '../util/util.js';
Expand Down Expand Up @@ -157,15 +157,15 @@ export class LDMLKeyboardXMLSourceFileReader {
if (!this.resolveOneImport(obj, subtag, {
base: constants.cldr_import_base,
path: constants.cldr_implied_keys_import
})) {
}, true)) {
return false;
}
} else if (subtag === 'forms') {
// <import base="cldr" path="techpreview/scanCodes-implied.xml"/>
if (!this.resolveOneImport(obj, subtag, {
base: constants.cldr_import_base,
path: constants.cldr_implied_forms_import
})) {
}, true)) {
return false;
}
}
Expand All @@ -176,9 +176,10 @@ export class LDMLKeyboardXMLSourceFileReader {
* @param obj the object being imported into
* @param subtag obj's element tag, e.g. `keys`
* @param asImport the import structure
* @param implied true if it is an implied import
* @returns true on success, false on failure
*/
private resolveOneImport(obj: any, subtag: string, asImport: LKImport) : boolean {
private resolveOneImport(obj: any, subtag: string, asImport: LKImport, implied? : boolean) : boolean {
const { base, path } = asImport;
if (base !== constants.cldr_import_base) {
this.callbacks.reportMessage(CommonTypesMessages.Error_ImportInvalidBase({base, path, subtag}));
Expand All @@ -205,12 +206,20 @@ export class LDMLKeyboardXMLSourceFileReader {
// pull all children of importXml[subtag] into obj
for (const subsubtag of Object.keys(importRootNode).reverse()) { // e.g. <key/>
const subsubval = importRootNode[subsubtag];
const basePath = `${base}/${path}`;
if (!Array.isArray(subsubval)) {
// This is somewhat of an internal error, indicating that a non-mergeable XML file was imported
// Not exercisable with the standard LDML imports.
this.callbacks.reportMessage(CommonTypesMessages.Error_ImportMergeFail({base, path, subtag, subsubtag}));
return false;
}
// Mark all children as an import
subsubval.forEach(o => o[ImportStatus.import] = basePath);
if (implied) {
// mark all children as an implied import
subsubval.forEach(o => o[ImportStatus.impliedImport] = basePath);
}

if (!obj[subsubtag]) {
obj[subsubtag] = []; // start with empty array
}
Expand Down
22 changes: 21 additions & 1 deletion common/web/types/src/ldml-keyboard/ldml-keyboard-xml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export interface LDMLKeyboardXMLSourceFile {
* <keyboard> -- the root element.
*/
keyboard3: LKKeyboard;
}
};

export interface LKKeyboard {
locale?: string;
Expand Down Expand Up @@ -193,3 +193,23 @@ export interface LKDisplays {
display?: LKDisplay[];
displayOptions?: LKDisplayOptions;
};

/**
* Utilities for determining the import status of items
*/
export class ImportStatus {
/** item came in via implied (spec based) import, such as keys-Latn-implied.xml */
static impliedImport = Symbol.for('@keymanapp:implied_import');
/** item came in via import */
static import = Symbol.for('@keymanapp:import');

/** @returns true if the object was loaded through an implied import */
static isImpliedImport(o : any) : boolean {
return o && !!o[ImportStatus.impliedImport];
}
/** @returns true if the object was loaded through an explicit import */
static isImport(o : any) : boolean {
return o && !!o[ImportStatus.import];
}
};

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LKKey } from './../../src/ldml-keyboard/ldml-keyboard-xml.js';
import { LKKey, ImportStatus } from './../../src/ldml-keyboard/ldml-keyboard-xml.js';
import 'mocha';
import {assert} from 'chai';
import { CommonTypesMessages } from '../../src/util/common-events.js';
Expand Down Expand Up @@ -40,6 +40,9 @@ describe('ldml keyboard xml reader tests', function () {
{id: 'b', to: 'b'},
{id: 'c', to: 'c'},
]);
// all of the keys are implied imports here
assert.isTrue(ImportStatus.isImpliedImport(source?.keyboard3?.keys.key.find(({id}) => id === 'a')));
assert.isTrue(ImportStatus.isImport(source?.keyboard3?.keys.key.find(({id}) => id === 'a')));
},
},
{
Expand Down Expand Up @@ -81,6 +84,15 @@ describe('ldml keyboard xml reader tests', function () {
{id: 'zz', to: 'zz'}, // new key
{id: 'hash', to: '##'}, // override
]);
// 'a' is an implied import
assert.isTrue(ImportStatus.isImpliedImport(k.find(({id}) => id === 'a')));
assert.isTrue(ImportStatus.isImport(k.find(({id}) => id === 'a')));
// 'hash' is an import but not implied
assert.isFalse(ImportStatus.isImpliedImport(k.find(({id}) => id === 'hash')));
assert.isTrue(ImportStatus.isImport(k.find(({id}) => id === 'hash')));
// 'zz' is not imported
assert.isFalse(ImportStatus.isImpliedImport(k.find(({id}) => id === 'zz')));
assert.isFalse(ImportStatus.isImport(k.find(({id}) => id === 'zz')));
},
},
{
Expand Down

0 comments on commit 3a677da

Please sign in to comment.