Skip to content

Commit

Permalink
refactor(web): move KeyboardObject type to common/web/types
Browse files Browse the repository at this point in the history
Fixes: #11612
  • Loading branch information
ermshiperete committed Oct 8, 2024
1 parent 044eea1 commit 3b9c6ef
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 210 deletions.
23 changes: 20 additions & 3 deletions common/web/types/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -82,9 +82,26 @@ function do_configure() {
function do_test() {
eslint .
tsc --build test
readonly C8_THRESHOLD=50
c8 -skip-full --reporter=lcov --reporter=text --lines $C8_THRESHOLD --statements $C8_THRESHOLD --branches $C8_THRESHOLD --functions $C8_THRESHOLD mocha "${builder_extra_params[@]}"
builder_echo warning "Coverage thresholds are currently $C8_THRESHOLD%, which is lower than ideal."

readonly C8_THRESHOLD=60
# Exclude files from coverage analysis that only define types:
exclude=(\
src/keyboard-object.ts \
src/lexical-model-types.ts \
src/outputTarget.interface.ts \
src/*.d.ts \
src/main.ts \
src/schemas/* \
src/schema-validators.ts \
src/schemas.ts \
)
# shellcheck disable=SC2068
c8 --skip-full --reporter=lcov --reporter=text --lines "${C8_THRESHOLD}" \
--statements "${C8_THRESHOLD}" --branches "${C8_THRESHOLD}" \
--functions "${C8_THRESHOLD}" ${exclude[@]/#/--exclude } \
mocha "${builder_extra_params[@]}"

builder_echo warning "Coverage thresholds are currently ${C8_THRESHOLD}%, which is lower than ideal."
builder_echo warning "Please increase threshold in build.sh as test coverage improves."
}

Expand Down
198 changes: 198 additions & 0 deletions common/web/types/src/keyboard-object.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* Keyman is copyright (C) SIL Global. MIT License.
*/
import { OutputTarget } from './outputTarget.interface.js';
import { TouchLayoutPlatform as LayoutFormFactorSpec } from './keyman-touch-layout/keyman-touch-layout-file.js';

export type ComplexKeyboardStore = (string | { t: 'd', d: number } | { ['t']: 'b' })[];

type KeyEvent = {};

/**
* Stores preprocessed properties of a keyboard for quick retrieval later.
*/
export class CacheTag {
stores: { [storeName: string]: ComplexKeyboardStore };

constructor() {
this.stores = {};
}
}

export interface EncodedVisualKeyboard {
/** Represents CSS font styling to use for VisualKeyboard text */
F: string;
/** Should there be a 102nd key? */
K102?: boolean,
/**
* Keyboard Layer Specification: an object-based map of layer name to the keycaps for its
* 65 keys. The 65 keys are ordered from left to right, then top to bottom.
*
* The key ID corresponding to each index of the array is specified within `Codes.dfltCodes`.
* Entries corresponding to `K_*` in `Codes.dfltCodes` are reserved for future use.
*/
KLS?: { [layerName: string]: string[] },
/**
* @deprecated
* The older form for data in KLS - defines keycaps for 'default' keys, then 'shift' keys,
* in a single concatenated array.
*/
BK?: string[];
}

export type LayoutSpec = {
"desktop"?: LayoutFormFactorSpec,
"phone"?: LayoutFormFactorSpec,
"tablet"?: LayoutFormFactorSpec
}

export type KeyboardObject = {
/**
* Used internally by Keyman Engine for Web to hold preprocessed stores.
*/
_kmw?: CacheTag;

/**
* group-start: the function triggering processing for the keyboard's
* "Unicode" start group, corresponding to `begin Unicode > use(_____)` in
* Keyman keyboard language.
* @param outputTarget The context to which the keystroke applies
* @param keystroke The full, pre-processed keystroke triggering
* keyboard-rule application.
*/
gs(outputTarget: OutputTarget, keystroke: KeyEvent): boolean;

/**
* group-newcontext: the function triggering processing for the keyboard's
* "NewContext" start group, corresponding to `begin NewContext > use(_____)`
* in Keyman keyboard language.
* @param outputTarget The new context to be used with future keystrokes
* @param keystroke A 'null' `KeyEvent` providing current modifier + state information.
*/
gn?(outputTarget: OutputTarget, keystroke: KeyEvent): boolean;

/**
* group-postkeystroke: the function triggering processing for the keyboard's
* "PostKeystroke" start group, corresponding to `begin PostKeystroke >
* use(_____)` in Keyman keyboard language.
* @param outputTarget The context altered by a recent keystroke. As a
* precondition, all changes due to `gs` / `begin Unicode` should already be
* applied.
* @param keystroke A 'null' `KeyEvent` providing current modifier + state information.
*/
gpk?(outputTarget: OutputTarget, keystroke: KeyEvent): boolean;

/**
* Keyboard ID: the uniquely-identifying name for this keyboard. Includes the standard
* `Keyboard_` prefix. May be 'namespaced' with a prefix corresponding to a package name
* within app/webview.
*/
KI: string;
/**
* Keyboard Name: the human-readable name of the keyboard.
*/
KN: string;
/**
* Encoded data usable to construct a desktop/hardware-oriented on-screen keyboard.
*/
KV: EncodedVisualKeyboard;
/**
* Keyboard Language Code: set within select keyboards.
*
* Currently, it's only used to determine the need for CJK-picker support. Is missing
* in most compiled keyboards.
*/
KLC?: string;
/**
* @deprecated
* Keyboard Language Code: set within select keyboards.
*
* Currently, it's only used to determine the need for CJK-picker support.
* Is (probably) an older name of KLC with the identical purpose. Is missing
* in most compiled keyboards.
*/
LanguageCode?: string;
/**
* Keyboard CSS: provides the definition for custom keyboard style sheets
*/
KCSS?: string;
/**
* Keyboard is RTL: a simple flag noting if the keyboard's script is RTL.
*/
KRTL?: boolean;
/**
* Keyboard Modifier BitMask: a set of bitflags indicating which modifiers
* the keyboard's rules utilize. See also: `ModifierKeyConstants`.
*/
KMBM?: number;
/**
* Keyboard Supplementary plane: set to 1 if the keyboard uses non-BMP Unicode
* characters.
*/
KS?: number;
/**
* Keyman Visual Keyboard Layout: defines the touch-layout definitions used for
* 'phone' and 'tablet' form-factors.
*/
KVKL?: LayoutSpec;
/**
* Keyboard is Mnemonic: set to 1 if the keyboard uses a mnemonic layout.
*/
KM?: number;
/**
* KeyBoard VERsion: the version of this keyboard.
*/
KBVER?: string;
/**
* Keyman VERsion: the version of Keyman Developer used to compile this keyboard.
*/
KVER?: string;
/**
* Keyman Variable Stores: an array of the names of all variable stores used by the
* keyboard.
*/
KVS?: (`s${number}`)[];
/**
* Keyboard Help: HTML help text, as specified by either the &kmw_helptext or &kmw_helpfile system stores.
*
* Reference: https://help.keyman.com/developer/language/reference/kmw_helptext,
* https://help.keyman.com/developer/language/reference/kmw_helpfile
*/
KH?: string;
/**
* Keyboard Virtual Key Dictionary: the Developer-compiled, minified dictionary of virtual-key codes
*/
KVKD?: string;
/**
* Keyboard Display Underlying: set to 1 if the desktop form of the keyboard
* should show the US QWERTY underlying keycaps. These may also appear on
* touch layouts if set and no touch-layout information is available.
*/
KDU?: number;
/**
* Virtual Key Dictionary: the engine pre-processed, unminified dictionary. This is built within
* Keyman Engine for Web at runtime as needed based on the definitions in `KVKD`.
*/
VKDictionary?: Record<string, number>,
/**
* Keyboard Help File: Embedded JS script designed for use with a keyboard's
* HTML help text. Always defined within the file referenced by &kmw_embedjs
* in a keyboard's source, though that file may also contain _other_ script
* definitions as well. (`KHF` must be explicitly defined within that file.)
* @param e Will be provided with the root element (a <div>) of the On-Screen Keyboard.
* @returns
*/
KHF?: (e: any) => string;

/**
* Keyboard Notify Shift: Provided by CJK-picker keyboards to properly
* interface them with Keyman Engine for Web.
* @param {number} _PCommand event code (16,17,18) or 0; 16-18
* correspond to modifier codes when pressed, while 0 corresponds to loss of focus
* @param {Object} _PTarget target element
* @param {number} _PData 1 or 0
* @returns
*/
KNS?: (_PCommand: number, _PTarget: OutputTarget, _PData: number) => void;
} & Record<`s${number}`, string>

3 changes: 3 additions & 0 deletions common/web/types/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ export { VariableParser, MarkerParser } from './ldml-keyboard/pattern-parser.js'
export { ElementString } from './kmx/kmx-plus/element-string.js';

export { USVString, CasingForm, CasingFunction, TextWithProbability, LexiconTraversal, LexicalModel, LexicalModelPunctuation, Transform, Suggestion, Reversion, Keep, SuggestionTag, Context, Distribution, Outcome, WithOutcome, ProbabilityMass, Configuration, Capabilities, WordBreakingFunction, Span } from './lexical-model-types.js';

export { CacheTag, ComplexKeyboardStore, EncodedVisualKeyboard, LayoutSpec, KeyboardObject } from './keyboard-object.js';
export { OutputTarget } from './outputTarget.interface.js';
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/*
* Keyman is copyright (C) SIL Global. MIT License.
*/
export interface OutputTarget {
/**
* Signifies that this OutputTarget has no default key processing behaviors. This should be false
Expand Down
3 changes: 2 additions & 1 deletion web/src/app/browser/src/keymanEngine.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { KeyboardObject } from '@keymanapp/common-types';
import { KeymanEngine as KeymanEngineBase, DeviceDetector } from 'keyman/engine/main';
import { getAbsoluteY } from 'keyman/engine/dom-utils';
import { OutputTarget } from 'keyman/engine/element-wrappers';
Expand All @@ -6,7 +7,7 @@ import {
VisualKeyboard
} from 'keyman/engine/osk';
import { ErrorStub, KeyboardStub, CloudQueryResult, toPrefixedKeyboardId as prefixed } from 'keyman/engine/keyboard-storage';
import { DeviceSpec, Keyboard, KeyboardObject } from "keyman/engine/keyboard";
import { DeviceSpec, Keyboard } from "keyman/engine/keyboard";

import * as views from './viewsAnchorpoint.js';
import { BrowserConfiguration, BrowserInitOptionDefaults, BrowserInitOptionSpec } from './configuration.js';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Suggestion, Reversion } from '@keymanapp/common-types';
import { OutputTarget, Suggestion, Reversion } from '@keymanapp/common-types';
import { EventEmitter } from "eventemitter3";
import { OutputTarget } from "keyman/engine/keyboard";

export class ReadySuggestions {
suggestions: Suggestion[];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { EventEmitter } from "eventemitter3";
import { Keep, Reversion, Suggestion } from '@keymanapp/common-types';
import { Keep, type OutputTarget, Reversion, Suggestion } from '@keymanapp/common-types';
import { type LanguageProcessorSpec , ReadySuggestions, type InvalidateSourceEnum, StateChangeHandler } from './languageProcessor.interface.js';
import { type OutputTarget } from "keyman/engine/keyboard";

interface PredictionContextEventMap {
update: (suggestions: Suggestion[]) => void;
Expand Down
3 changes: 1 addition & 2 deletions web/src/engine/js-processor/src/outputTarget.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { extendString } from "@keymanapp/web-utils";
import { findCommonSubstringEndIndex } from "./stringDivergence.js";
import { Mock } from "./mock.js";
import { OutputTarget as OutputTargetInterface } from 'keyman/engine/keyboard';

extendString();

// Defines deadkey management in a manner attachable to each element interface.
import { type KeyEvent } from 'keyman/engine/keyboard';
import { Deadkey, DeadkeyTracker } from "./deadkeys.js";
import { ProbabilityMass, Transform } from '@keymanapp/common-types';
import { OutputTarget as OutputTargetInterface, ProbabilityMass, Transform } from '@keymanapp/common-types';

// Also relies on string-extensions provided by the web-utils package.

Expand Down
3 changes: 1 addition & 2 deletions web/src/engine/keyboard/src/defaultRules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
* Implementation of default rules
*/

import { ModifierKeyConstants } from '@keymanapp/common-types';
import { ModifierKeyConstants, type OutputTarget } from '@keymanapp/common-types';
import Codes from './codes.js';
import type KeyEvent from './keyEvent.js';
import { type OutputTarget } from './outputTarget.interface.js';

export enum EmulationKeystrokes {
Enter = '\n',
Expand Down
3 changes: 1 addition & 2 deletions web/src/engine/keyboard/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ export * from "./defaultRules.js";
export { default as KeyEvent } from "./keyEvent.js";
export * from "./keyEvent.js";
export { default as KeyMapping } from "./keyMapping.js";
export { OutputTarget } from "./outputTarget.interface.js";

export * from "@keymanapp/web-utils";

// At the top level, there should be no default export.

// Without the line below... OutputTarget would likely be aliased there, as it's
// Without the line below... KeyMapping would likely be aliased there, as it's
// the last `export { default as _ }` => `export * from` pairing seen above.
export default undefined;
29 changes: 1 addition & 28 deletions web/src/engine/keyboard/src/keyboards/defaultLayouts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
***/

import { Version, deepCopy } from "@keymanapp/web-utils";
import { ModifierKeyConstants, TouchLayout } from "@keymanapp/common-types";
import { EncodedVisualKeyboard, LayoutSpec, ModifierKeyConstants, TouchLayout } from "@keymanapp/common-types";

import LayoutFormFactorSpec = TouchLayout.TouchLayoutPlatform;
import LayoutLayerBase = TouchLayout.TouchLayoutLayer;
Expand All @@ -19,27 +19,6 @@ export { ButtonClasses };
import Codes from "../codes.js";
import type Keyboard from "./keyboard.js";

export interface EncodedVisualKeyboard {
/** Represents CSS font styling to use for VisualKeyboard text */
F: string;
/** Should there be a 102nd key? */
K102?: boolean,
/**
* Keyboard Layer Specification: an object-based map of layer name to the keycaps for its
* 65 keys. The 65 keys are ordered from left to right, then top to bottom.
*
* The key ID corresponding to each index of the array is specified within `Codes.dfltCodes`.
* Entries corresponding to `K_*` in `Codes.dfltCodes` are reserved for future use.
*/
KLS?: {[layerName: string]: string[]},
/**
* @deprecated
* The older form for data in KLS - defines keycaps for 'default' keys, then 'shift' keys,
* in a single concatenated array.
*/
BK?: string[];
}

// The following types provide type definitions for the full JSON format we use for visual keyboard definitions.
export type ButtonClass = 0 | 1 | 2 | 3 | 4 | /*5 | 6 | 7 |*/ 8 | 9 | 10;

Expand All @@ -57,12 +36,6 @@ export interface LayoutFormFactor extends LayoutFormFactorSpec {
layer: LayoutLayer[]
};

export type LayoutSpec = {
"desktop"?: LayoutFormFactorSpec,
"phone"?: LayoutFormFactorSpec,
"tablet"?: LayoutFormFactorSpec
}

const KEY_102_WIDTH = 200;

// This class manages default layout construction for consumption by OSKs without a specified layout.
Expand Down
Loading

0 comments on commit 3b9c6ef

Please sign in to comment.