From c1439759ca34e69ec97236718ef5dbf7a75f494f Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 25 Nov 2022 19:31:55 +0700 Subject: [PATCH 01/21] chore: temp step 1 of ts kmw --- common/windows/cpp/include/legacy_kmx_file.h | 3 +- .../src/common/delphi/compiler/compile.pas | 28 +- developer/src/kmc-kmw/Makefile | 39 ++ developer/src/kmc-kmw/build.sh | 73 ++++ developer/src/kmc-kmw/package.json | 54 +++ .../src/kmc-kmw/src/compiler/callbacks.ts | 11 + .../kmc-kmw/src/compiler/compiler-options.ts | 13 + .../src/compiler/keymanweb-compiler.ts | 82 ++++ .../src/kmc-kmw/src/compiler/messages.ts | 97 +++++ .../src/compiler/write-compiled-keyboard.ts | 408 ++++++++++++++++++ developer/src/kmc-kmw/src/main.ts | 2 + developer/src/kmc-kmw/src/util/util.ts | 7 + developer/src/kmc-kmw/tsconfig.json | 25 ++ developer/src/kmcmpdll/Compiler.cpp | 7 +- developer/src/kmcomp/kmcomp.dproj | 2 +- .../src/tike/compile/CompileKeymanWeb.pas | 35 ++ 16 files changed, 882 insertions(+), 4 deletions(-) create mode 100644 developer/src/kmc-kmw/Makefile create mode 100755 developer/src/kmc-kmw/build.sh create mode 100644 developer/src/kmc-kmw/package.json create mode 100644 developer/src/kmc-kmw/src/compiler/callbacks.ts create mode 100644 developer/src/kmc-kmw/src/compiler/compiler-options.ts create mode 100644 developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts create mode 100644 developer/src/kmc-kmw/src/compiler/messages.ts create mode 100644 developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts create mode 100644 developer/src/kmc-kmw/src/main.ts create mode 100644 developer/src/kmc-kmw/src/util/util.ts create mode 100644 developer/src/kmc-kmw/tsconfig.json diff --git a/common/windows/cpp/include/legacy_kmx_file.h b/common/windows/cpp/include/legacy_kmx_file.h index ae18543312..4aca74ed3d 100644 --- a/common/windows/cpp/include/legacy_kmx_file.h +++ b/common/windows/cpp/include/legacy_kmx_file.h @@ -416,7 +416,8 @@ typedef COMPILER_OPTIONS *PCOMPILER_OPTIONS; typedef int (CALLBACK *CompilerMessageProc)(int line, DWORD dwMsgCode, LPSTR szText); -//extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL FSaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc); // I4865 // I4866 +extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL FSaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc); // I4865 // I4866 +extern "C" BOOL __declspec(dllexport) CompileKeyboardFileEx(PSTR pszInfile, PSTR pszOutfile, BOOL ASaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc, int Target); #endif // _COMPILER_H diff --git a/developer/src/common/delphi/compiler/compile.pas b/developer/src/common/delphi/compiler/compile.pas index 9b304b39d8..9ebea18ad2 100644 --- a/developer/src/common/delphi/compiler/compile.pas +++ b/developer/src/common/delphi/compiler/compile.pas @@ -167,6 +167,7 @@ const function CompileKeyboardFile(kmnFile, kmxFile: PChar; FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; CallBack: TCompilerCallback): Integer; cdecl; // I4865 // I4866 function CompileKeyboardFileToBuffer(kmnFile: PChar; buf: PFILE_KEYBOARD; CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; CallBack: TCompilerCallback; Target: Integer): Integer; cdecl; // I4865 // I4866 +function CompileKeyboardFileEx(kmnFile, kmxfile: PChar; FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; CallBack: TCompilerCallback; Target: Integer): Integer; // I4865 // I4866 function Compiler_Diagnostic(mode: Integer): Integer; procedure Compiler_Diagnostic_Console(mode: Integer); @@ -200,13 +201,18 @@ var HKMCmpDll: THandle = 0; type - TCompileKeyboardFile = function (kmnFile, kmxFile: PAnsiChar; FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; // I3310 // I4865 // I4866 + TCompileKeyboardFile = function (kmnFile, kmxFile: PAnsiChar; + FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; // I3310 // I4865 // I4866 CallBack: TCompilerCallback): Integer; cdecl; // TODO: K9: Convert to Unicode TCompileKeyboardFileToBuffer = function (kmnFile: PAnsiChar; buf: PFILE_KEYBOARD; // I3310 CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; // I4865 // I4866 CallBack: TCompilerCallback; Target: Integer): Integer; cdecl; // TODO: K9: Convert to Unicode + TCompileKeyboardFileEx = function (kmnFile, kmxFile: PAnsiChar; + FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; + CallBack: TCompilerCallback; Target: Integer): Integer; cdecl; // TODO: K9: Convert to Unicode + TSetCompilerOptions = function (options: PCOMPILER_OPTIONS): BOOL; cdecl; function LoadCompiler(CallBack: TCompilerCallback = nil): Boolean; @@ -303,6 +309,26 @@ begin Result := ckf(PAnsiChar(AnsiString(kmnFile)), buf, CompilerWarningsAsErrors, WarnDeprecatedCode, Callback, Target); // I3310 // I4865 // I4866 end; +function CompileKeyboardFileEx(kmnFile, kmxfile: PChar; FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; CallBack: TCompilerCallback; Target: Integer): Integer; // I4865 // I4866 +var + ckf: TCompileKeyboardFileEx; +begin + //Result := 0; + + if not LoadCompiler(Callback) then Exit(-1); + + @ckf := GetProcAddress(HKMCmpDll, 'CompileKeyboardFileEx'); + if not Assigned(@ckf) then + begin + Callback(0, $8000, PAnsiChar(AnsiString('Could not access the compiler. Check that '+kmcmpdll_lib+' is in the program directory '+ // I4706 + 'and that it is not corrupt.'#13#10+'Windows error message: '+SysErrorMessage(GetLastError)))); + Result := -1; + Exit; + end; + + Result := ckf(PAnsiChar(AnsiString(kmnFile)), PAnsiChar(AnsiString(kmxfile)), FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode, Callback, Target); // I3310 // I4865 // I4866 +end; + type TKeyman_Diagnostic = procedure(mode: Integer); cdecl; diff --git a/developer/src/kmc-kmw/Makefile b/developer/src/kmc-kmw/Makefile new file mode 100644 index 0000000000..c9ae1e81a6 --- /dev/null +++ b/developer/src/kmc-kmw/Makefile @@ -0,0 +1,39 @@ +# +# Keyman Developer - kmc KMW Keyboard Compiler Makefile +# + +!include ..\Defines.mak + +# We do configure here because parent Makefile calls this first; other +# kmc and kmc-* makefiles don't do it +build: configure .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh build + +configure: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh configure + +clean: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh clean + +test: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh test + +# build.sh bundle must be run from shell as it requires a temp folder to be +# passed in. See inst/download.in.mak for instantiation. + +publish: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh publish + +signcode: + @rem nothing to do + +wrap-symbols: + @rem nothing to do + +test-manifest: + @rem nothing to do + +install: + @rem nothing to do + +!include ..\Target.mak diff --git a/developer/src/kmc-kmw/build.sh b/developer/src/kmc-kmw/build.sh new file mode 100755 index 0000000000..684f5f7911 --- /dev/null +++ b/developer/src/kmc-kmw/build.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# +# Compiles the kmc KeymanWeb keyboard compiler. +# + +# Exit on command failure and when using unset variables: +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../resources/build/build-utils.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +cd "$THIS_SCRIPT_PATH" + +. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" + +builder_describe "Build Keyman kmc KMW Keyboard Compiler module" \ + "@/common/web/keyman-version" \ + "@/common/web/types" \ + "configure" \ + "build" \ + "clean" \ + "test" \ + "publish publish to npm" \ + "--dry-run,-n don't actually publish, just dry run" +builder_describe_outputs \ + configure /node_modules \ + build build/src/main.js + +builder_parse "$@" + +#------------------------------------------------------------------------------------------------------------------- + +if builder_start_action clean; then + rm -rf ./build/ ./tsconfig.tsbuildinfo + builder_finish_action success clean +else + # We need the schema file at runtime and bundled, so always copy it for all actions except `clean` + mkdir -p "$THIS_SCRIPT_PATH/build/src/" + cp "$KEYMAN_ROOT/common/schemas/keyman-touch-layout/keyman-touch-layout.spec.json" "$THIS_SCRIPT_PATH/build/src/" + cp "$KEYMAN_ROOT/common/schemas/kvks/kvks.schema.json" "$THIS_SCRIPT_PATH/build/src/" +fi + +#------------------------------------------------------------------------------------------------------------------- + +if builder_start_action configure; then + verify_npm_setup + builder_finish_action success configure +fi + +#------------------------------------------------------------------------------------------------------------------- + +if builder_start_action build; then + npm run build + builder_finish_action success build +fi + +#------------------------------------------------------------------------------------------------------------------- + +if builder_start_action test; then + npm test + builder_finish_action success test +fi + +#------------------------------------------------------------------------------------------------------------------- + +if builder_start_action publish; then + . "$KEYMAN_ROOT/resources/build/npm-publish.inc.sh" + npm_publish + builder_finish_action success publish +fi diff --git a/developer/src/kmc-kmw/package.json b/developer/src/kmc-kmw/package.json new file mode 100644 index 0000000000..e41821bf22 --- /dev/null +++ b/developer/src/kmc-kmw/package.json @@ -0,0 +1,54 @@ +{ + "name": "@keymanapp/kmc-kmw", + "description": "Keyman Developer KMW keyboard compiler", + "keywords": [ + "keyboard", + "keyman", + "ldml", + "unicode" + ], + "type": "module", + "exports": { + ".": "./build/src/main.js" + }, + "scripts": { + "build": "tsc -b", + "test": "cd test && tsc -b && cd .. && c8 mocha", + "prepublishOnly": "npm run build" + }, + "author": "Marc Durdin (https://github.com/mcdurdin)", + "license": "MIT", + "bugs": { + "url": "https://github.com/keymanapp/keyman/issues" + }, + "dependencies": { + "@keymanapp/keyman-version": "*", + "ajv": "^8.11.0", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "semver": "^7.3.7", + "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" + }, + "devDependencies": { + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.7", + "@types/node": "^10.14.6", + "@types/semver": "^7.3.12", + "@types/xml2js": "^0.4.5", + "c8": "^7.12.0", + "chai": "^4.3.4", + "chalk": "^2.4.2", + "mocha": "^8.4.0", + "ts-node": "^9.1.1", + "typescript": "4.6.3" + }, + "mocha": { + "spec": "build/test/**/test-*.js", + "require": [ + "source-map-support/register" + ] + }, + "repository": { + "type": "git", + "url": "git+https://github.com/keymanapp/keyman.git" + } +} diff --git a/developer/src/kmc-kmw/src/compiler/callbacks.ts b/developer/src/kmc-kmw/src/compiler/callbacks.ts new file mode 100644 index 0000000000..f6cd673b56 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/callbacks.ts @@ -0,0 +1,11 @@ +export interface CompilerEvent { + code: number; + message: string; +}; + +export default interface CompilerCallbacks { + loadFile(baseFilename: string, filename: string): Buffer; + loadLdmlKeyboardSchema(): Buffer; + loadKvksJsonSchema(): Buffer; + reportMessage(event: CompilerEvent): void; +}; diff --git a/developer/src/kmc-kmw/src/compiler/compiler-options.ts b/developer/src/kmc-kmw/src/compiler/compiler-options.ts new file mode 100644 index 0000000000..76dd4b5ba4 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/compiler-options.ts @@ -0,0 +1,13 @@ + + +export default interface CompilerOptions { + /** + * Add debug information to the .kmx file when compiling + */ + debug: boolean; + + /** + * Add metadata about the compiler version to .kmx file when compiling + */ + addCompilerVersion: boolean; +}; diff --git a/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts b/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts new file mode 100644 index 0000000000..03fc953e3f --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts @@ -0,0 +1,82 @@ +import { VisualKeyboard } from "@keymanapp/common-types"; + +import * as path from 'path'; +import { KMXFile } from "../../../../../common/web/types/src/kmx/kmx"; +// import VisualKeyboardCompiler from "./visual-keyboard-compiler.js"; + +export interface KeymanWebCompilerOptions { + debug?: boolean; +}; + +export class KeymanWebCompiler { + private readonly options: KeymanWebCompilerOptions; + private readonly nl: string; + private readonly tab: string; + + constructor(options?: KeymanWebCompilerOptions) { + this.options = options; + this.nl = this.options.debug ? "\n" : ''; + this.tab = this.options.debug ? " " : ''; + } + + public compile(name: string, source: KMXFile): string { + const nl = this.nl, tab = this.tab; + + // TODO: fill in from CompileKeymanWeb.pas + + const sName = 'Keyboard_'+this.cleanName(name); + const displayUnderlying = true; // TODO-LDML + const modifierBitmask = 0; // TODO-LDML: define the modifiers used by this keyboard + const vkDictionary = ''; // TODO-LDML: vk dictionary for touch keys + const hasSupplementaryPlaneChars = false; // TODO-LDML + const isRTL = false; // TODO-LDML + + let result = + `if(typeof keyman === 'undefined') {${nl}` + + `${tab}console.error('Keyboard requires KeymanWeb ${MINIMUM_KMW_VERSION} or later');${nl}` + + `} else {${nl}` + + `${tab}KeymanWeb.KR(new ${sName}());${nl}` + + `}${nl}` + + `function ${sName}() {${nl}` + + // `${tab}${this.setupDebug()}${nl}` + ? we may use this for modifierBitmask in future + // `${tab}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` + ? we probably don't need this, it's for back-compat + `${tab}this.KI="${sName}";${nl}` + + `${tab}this.KN=${JSON.stringify(source.keyboard.names.name[0])};${nl}` + + `${tab}this.KMINVER=${JSON.stringify(MINIMUM_KMW_VERSION)};${nl}` + + `${tab}this.KV=${this.compileVisualKeyboard(source)};${nl}` + + `${tab}this.KDU=${displayUnderlying ? '1' : '0'};${nl}` + + `${tab}this.KH="";${nl}` + // TODO-LDML: help text not supported + `${tab}this.KM=0;${nl}` + // TODO-LDML: mnemonic layout not supported for LDML keyboards + `${tab}this.KBVER=${JSON.stringify(source.keyboard.version.number)};${nl}` + + `${tab}this.KMBM=${modifierBitmask};${nl}`; + + if(isRTL) { + result += `${tab}this.KRTL=1;${nl}`; + } + + if(hasSupplementaryPlaneChars) { + result += `${tab}this.KS=1;${nl}`; + } + + if(vkDictionary != '') { + result += `${tab}this.KVKD=${JSON.stringify(vkDictionary)};${nl}`; + } + + let layoutFile = this.compileTouchLayout(source); + if(layoutFile != '') { + result += `${tab}this.KVKL=${layoutFile};${nl}`; + } + // TODO-LDML: KCSS not supported + + // TODO-LDML: embed binary keyboard for loading into Core + + // A LDML keyboard has a no-op for its gs() (begin Unicode) function, + // because the functionality is embedded in Keyman Core + result += `${tab}this.gs=function(t,e){${nl}`+ + `${tab}${tab}return 0;${nl}`+ // TODO-LDML: we will start by embedding call into Keyman Core here + `${tab}};${nl}`; + + result += `}${nl}`; + return result; + } +} \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/messages.ts b/developer/src/kmc-kmw/src/compiler/messages.ts new file mode 100644 index 0000000000..0a6801f9d2 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/messages.ts @@ -0,0 +1,97 @@ + +export enum CompilerErrorSeverity { + Info = 0x000000, + Hint = 0x100000, + Warn = 0x200000, + Error = 0x300000, + Fatal = 0x400000, + Severity_Mask = 0xF00000, // includes reserved bits + Error_Mask = 0x0FFFFF, +}; + +const m = (code: number, message: string) => { return { code, message } }; +const SevInfo = CompilerErrorSeverity.Info; +const SevHint = CompilerErrorSeverity.Hint; +// const SevWarn = CompilerErrorSeverity.Warn; +const SevError = CompilerErrorSeverity.Error; +const SevFatal = CompilerErrorSeverity.Fatal; + +export class CompilerMessages { + static Error_InvalidNormalization = (o:{form: string}) => m(this.ERROR_InvalidNormalization, `Invalid normalization form '${o.form}`); + static ERROR_InvalidNormalization = SevError | 0x0001; + + static Error_InvalidLocale = (o:{tag: string}) => m(this.ERROR_InvalidLocale, `Invalid BCP 47 locale form '${o.tag}'`); + static ERROR_InvalidLocale = SevError | 0x0002; + + static Error_HardwareLayerHasTooManyRows = () => m(this.ERROR_HardwareLayerHasTooManyRows, `'hardware' layer has too many rows`); + static ERROR_HardwareLayerHasTooManyRows = SevError | 0x0003; + + static Error_RowOnHardwareLayerHasTooManyKeys = (o:{row: number}) => m(this.ERROR_RowOnHardwareLayerHasTooManyKeys, `Row #${o.row} on 'hardware' layer has too many keys`); + static ERROR_RowOnHardwareLayerHasTooManyKeys = SevError | 0x0004; + + static Error_KeyNotFoundInKeyBag = (o:{keyId: string, col: number, row: number, layer: string, form: string}) => + m(this.ERROR_KeyNotFoundInKeyBag, `Key '${o.keyId}' in position #${o.col} on row #${o.row} of layer ${o.layer}, form '${o.form}' not found in key bag`); + static ERROR_KeyNotFoundInKeyBag = SevError | 0x0005; + + static Hint_OneOrMoreRepeatedLocales = () => + m(this.HINT_OneOrMoreRepeatedLocales, `After minimization, one or more locales is repeated and has been removed`); + static HINT_OneOrMoreRepeatedLocales = SevHint | 0x0006; + + static Error_InvalidFile = (o:{errorText: string}) => + m(this.ERROR_InvalidFile, `The source file has an invalid structure: ${o.errorText}`); + static ERROR_InvalidFile = SevError | 0x0007; + + static Hint_LocaleIsNotMinimalAndClean = (o:{sourceLocale: string, locale: string}) => + m(this.HINT_LocaleIsNotMinimalAndClean, `Locale '${o.sourceLocale}' is not minimal or correctly formatted and should be '${o.locale}'`); + static HINT_LocaleIsNotMinimalAndClean = SevHint | 0x0008; + + static Error_VkeyIsNotValid = (o:{vkey: string}) => + m(this.ERROR_VkeyIsNotValid, `Virtual key '${o.vkey}' is not found in the CLDR VKey Enum table.`); + static ERROR_VkeyIsNotValid = SevError | 0x0009; + + static Hint_VkeyIsRedundant = (o:{vkey: string}) => + m(this.HINT_VkeyIsRedundant, `Virtual key '${o.vkey}' is mapped to itself, which is redundant.`); + static HINT_VkeyIsRedundant = SevHint | 0x000A; + + static Error_VkeyIsRepeated = (o:{vkey: string}) => + m(this.ERROR_VkeyIsRepeated, `Virtual key '${o.vkey}' has more than one vkey entry.`); + static ERROR_VkeyIsRepeated = SevError | 0x000B; + + static Info_MultipleVkeysHaveSameTarget = (o:{vkey: string}) => + m(this.INFO_MultipleVkeysHaveSameTarget, `Target virtual key '${o.vkey}' has multiple source mappings, which may be an error.`); + static INFO_MultipleVkeysHaveSameTarget = SevInfo | 0x000C; + + static Error_InvalidVersion = (o:{version: string}) => + m(this.ERROR_InvalidVersion, `Version number '${o.version}' must be a semantic version format string.`); + static ERROR_InvalidVersion = SevError | 0x000D; + + static Error_MustBeAtLeastOneLayerElement = () => + m(this.ERROR_MustBeAtLeastOneLayerElement, `The source file must contain at least one layer element.`); + static ERROR_MustBeAtLeastOneLayerElement = SevError | 0x000E; + + static Fatal_SectionCompilerFailed = (o:{sect: string}) => + m(this.FATAL_SectionCompilerFailed, `The compiler for '${o.sect}' failed unexpectedly.`); + static FATAL_SectionCompilerFailed = SevFatal | 0x000F; + + static Error_DisplayIsRepeated = (o:{to: string}) => + m(this.ERROR_DisplayIsRepeated, `display to='${o.to}' has more than one display entry.`); + static ERROR_DisplayIsRepeated = SevError | 0x0010; + + static Error_KeyMissingToGapOrSwitch = (o:{keyId: string}) => + m(this.ERROR_KeyMissingToGapOrSwitch, `key id='${o.keyId}' must have either to=, gap=, or switch=.`); +static ERROR_KeyMissingToGapOrSwitch = SevError | 0x0011; + + static severityName(code: number): string { + let severity = code & CompilerErrorSeverity.Severity_Mask; + switch(severity) { + case CompilerErrorSeverity.Info: return 'INFO'; + case CompilerErrorSeverity.Hint: return 'HINT'; + case CompilerErrorSeverity.Warn: return 'WARN'; + case CompilerErrorSeverity.Error: return 'ERROR'; + case CompilerErrorSeverity.Fatal: return 'FATAL'; + /* istanbul ignore next */ + default: return 'UNKNOWN'; + } + } +} + diff --git a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts new file mode 100644 index 0000000000..603b2be784 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts @@ -0,0 +1,408 @@ +import { GROUP, KEY, KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx"; + +function requote(s: string): string { + return "'" + s.replaceAll(/(['\\])/, "\\$1") + "'"; +} + +export function WriteCompiledKeyboard(source: KMXFile): string { + // let fgp: GROUP; + let fsp: STORE; + let fkp: KEY; + + let j: number; + let n: number; + + let vMnemonic: number = 0; + let s: string, sRTL: string = "", sHelp: string = "''", sHelpFile: string = "", + sEmbedJS: string = "", sEmbedCSS: string = ""; + let sVisualKeyboard: string = "", sFullName: string = ""; + let sBegin_NewContext: string, sBegin_PostKeystroke: string; + let sLayoutFile: string = "", sVKDictionary: string; + let linecomment: string; // I3438 + let HasRules: boolean; + let sModifierBitmask: string; + let FOptionStores: string; + let FKeyboardVersion = "1.0"; + // let rec: TSentinelRecord; + + let result = ""; + // Locate the name of the keyboard + for(let i = 0; i < source.keyboard.stores.length; i++) { + const fsp = source.keyboard.stores[i]; + if(fsp.dwSystemID == KMXFile.TSS_NAME) { + sFullName = fsp.dpString; + } + else if(fsp.dwSystemID == KMXFile.TSS_KEYBOARDVERSION) { // I4155 + FKeyboardVersion = fsp.dpString; + } + else if (fsp.dpName == 'HelpFile' || fsp.dwSystemID == KMXFile.TSS_KMW_HELPFILE) { + sHelpFile = fsp.dpString; + } + else if (fsp.dpName == 'Help' || fsp.dwSystemID == KMXFile.TSS_KMW_HELPTEXT) { + sHelp = '"'+RequotedString(fsp.dpString)+'"'; + } + else if (fsp.dpName == 'VisualKeyboard' || fsp.dwSystemID == KMXFile.TSS_VISUALKEYBOARD) { + sVisualKeyboard = fsp.dpString; + } + else if (fsp.dpName == 'EmbedJS' || fsp.dwSystemID == KMXFile.TSS_KMW_EMBEDJS) { + sEmbedJS = fsp.dpString; + } + else if (fsp.dpName == 'EmbedCSS' || fsp.dwSystemID == KMXFile.TSS_KMW_EMBEDCSS) { // I4368 + sEmbedCSS = fsp.dpString; + } + else if (fsp.dpName == 'RTL' || fsp.dwSystemID == KMXFile.TSS_KMW_RTL) { + sRTL = fsp.dpString == '1' ? FTabStop+'this.KRTL=1;'+nl : ''; // I3681 + } + else if (fsp.dwSystemID == KMXFile.TSS_MNEMONIC) { + vMnemonic = fsp.dpString == '1' ? 1 : 0; + } + else if (fsp.dwSystemID == KMXFile.TSS_VKDICTIONARY) { // I3438 + sVKDictionary = fsp.dpString; + } + else if (fsp.dwSystemID == KMXFile.TSS_LAYOUTFILE) { // I3483 + sLayoutFile = fsp.dpString; + } + else if (fsp.dwSystemID == KMXFile.TSS_BEGIN_NEWCONTEXT) { + sBegin_NewContext = fsp.dpString; + } + else if (fsp.dwSystemID -= KMXFile.TSS_BEGIN_POSTKEYSTROKE) { + sBegin_PostKeystroke = fsp.dpString; + } + } + + const sName = 'Keyboard_'+TKeyboardUtils.GetKeymanWebCompiledNameFromFileName(FInFile); + + if (sHelpFile != '') { + sHelp = ''; + //TODO: load sHelpFile from file + /*with TStringList.Create do + try + try + LoadFromFile(ExtractFilePath(FInFile) + sHelpFile, TEncoding.UTF8); // I3337 + for n := 0 to Count - 1 do + sHelp := sHelp + Strings[n] + ' '; + except + on E:EFOpenError do + begin + ReportError(0, CWARN_HelpFileMissing, E.Message); // I1971 // I4061 + sHelp := ''; + end; + end; + finally + Free; + end;*/ + + sHelp = requote(sHelp); + } + + if (sEmbedJS != '') { + //TODO: load sEmbedJS from file + /*try + with TStringList.Create do + try + LoadFromFile(ExtractFilePath(FInFile) + sEmbedJS, TEncoding.UTF8); // I3337 + sEmbedJS := Text; + finally + Free; + end; + except + on E:EFOpenError do // I3683 + begin + ReportError(0, CWARN_EmbedJsFileMissing, E.Message); // I4061 + sEmbedJS := ''; + end; + end;*/ + } + + if (sEmbedCSS != '') { // I4368 + //TODO: load sEmbedCSS from file + /*try + with TStringList.Create do + try + LoadFromFile(ExtractFilePath(FInFile) + sEmbedCSS, TEncoding.UTF8); // I3337 + sEmbedCSS := Text; + finally + Free; + end; + except + on E:EFOpenError do // I3683 + begin + ReportError(0, CWARN_EmbedJsFileMissing, E.Message); // I4061 + sEmbedCSS := ''; + end; + end;*/ + } + + if (sLayoutFile != '') { // I3483 + // TODO: Load sLayoutFile from file + /*try + with TStringList.Create do + try + LoadFromFile(ExtractFilePath(FInFile) + sLayoutFile, TEncoding.UTF8); + sLayoutFile := Text; + if not ValidateLayoutFile(sLayoutFile, sVKDictionary) then // I4060 + begin + sLayoutFile := ''; + end; + finally + Free; + end; + except + on E:EFOpenError do // I3683 + begin + ReportError(0, CWARN_TouchLayoutFileMissing, E.Message); // I4061 + sLayoutFile := ''; + end; + end;*/ + } + + // Default to hide underlying layout characters. This is overridden by touch + // layout platform.displayUnderlying property or, if that is not present for + // the given platform, by the OSK property. + let fDisplayUnderlying = false; + + if (sVisualKeyboard != '') { + //TODO: Load sVisualKeyboard from file + /* + try + // The Keyman .kmx compiler will change the value of this store from a + // .kvks to a .kvk during the build. Earlier in the build, the visual keyboard + // would have been compiled, so we need to account for that and use that file. + + sVisualKeyboard := VisualKeyboardFromFile(ExtractFilePath(FOutFile) + sVisualKeyboard, fDisplayUnderlying); + except + on E:EFOpenError do // I3947 + begin + ReportError(0, CWARN_VisualKeyboardFileMissing, E.Message); // I4061 + sVisualKeyboard := 'null'; + end; + end; + */ + } + else { + sVisualKeyboard = 'null'; + } + + sModifierBitmask = GetKeyboardModifierBitmask; + + fMnemonic = vMnemonic == 1; + + let nl = '';//TODO + let FTabStop = '';//TODO + + + result += + `${JavaScript_SetupProlog}${nl}` + + `'KeymanWeb.KR(new ${sName}());${nl}` + + `${JavaScript_SetupEpilog}${nl}` + + `function ${sName}()${nl}` + + `{${nl}` + + `${FTabStop}${JavaScript_SetupDebug}${nl}` + + // Following line caches the Keyman major version + `${FTabStop}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` + + `${FTabStop}this.KI="${sName}";${nl}` + + `${FTabStop}this.KN="%s";${nl}` + , RequotedString(sFullName), nl, + `${FTabStop}this.KMINVER="${(fk.version & VERSION_MASK_MAJOR) >> 8}.${fkp.version & VERSION_MASK_MINOR}";${nl}` + + `${FTabStop}this.KV=${sVisualKeyboard};${nl}` + + `${FTabStop}this.KDU=${fDisplayUnderlying?'1':'0'};${nl}` + + `${FTabStop}this.KH=${sHelp};${nl}` + + `${FTabStop}this.KM=${vMnemonic};${nl}` + + `${FTabStop}this.KBVER="${FKeyboardVersion}";${nl}` + // I4155 + `${FTabStop}this.KMBM=${sModifierBitmask};${nl}` + + `${sRTL}`; // I3681 + + if (HasSupplementaryPlaneChars) { + result += `${FTabStop}this.KS=1;${nl}`; + } + + if (sVKDictionary != '') { // I3438 + result += `${FTabStop}this.KVKD="${RequotedString(sVKDictionary)}";${nl}`; // I3681 + } + + if (sLayoutFile != '') { // I3483 + result += `${FTabStop}this.KVKL=${sLayoutFile};${nl}`; // I3681 + } + + if (sEmbedCSS != '') { // I4368 + result += `${FTabStop}this.KCSS="${RequotedString(sEmbedCSS)}";${nl}`; + } + + // Write the stores out + FOptionStores = ''; + for(let i = 0; i < source.keyboard.stores.length; i++) { + let fsp = source.keyboard.stores[i]; + // I3438 - Save all system stores to the keyboard, for now // I3684 + + if (!fsp.fIsDebug) { // and not (fsp.dwSystemID in [TSS_BITMAP, TSS_NAME, TSS_VERSION, TSS_CUSTOMKEYMANEDITION, TSS_CUSTOMKEYMANEDITIONNAME, TSS_KEYMANCOPYRIGHT]) then + if (fsp.dwSystemID == KMXFile.TSS_COMPARISON) { + result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(fsp.line, fsp.dpString)};${nl}`; + } + else if (fsp.dwSystemID == KMXFile.TSS_COMPILEDVERSION) { + result += `${FTabStop}this.KVER=${JavaScript_Store(fsp.line, fsp.dpString)};${nl}`; + } + //else if fsp.dwSystemID = TSS_VKDICTIONARY then // I3438, required for vkdictionary + // Result := Result + Format('%sthis.s%s=%s;%s', [FTabStop, JavaScript_Name(i, fsp.szName), JavaScript_Store(fsp.line, fsp.dpString), nl]) + else if (fsp.fIsOption && !fsp.fIsReserved) { + result += `${FTabStop}this.s${JavaScript_Name(i,fsp.szName)}=KeymanWeb.KLOAD(this.KI,"${JavaScript_Name(i,fsp.szName,true)}",`+ + `${JavaScript_Store(fsp.line, fsp.dpString)});${nl}`; + + if (FOptionStores != '') { + FOptionStores += ','; + } + FOptionStores += `'s${JavaScript_Name(i,fsp.szName)}`; + } + else if (fsp.dwSystemID == KMXFile.TSS_NONE /* aka not fsp.fIsReserved */) { + result += `${FTabStop}this.s${JavaScript_Name(i, fsp.szName)}=${JavaScript_Store(fsp.line, fsp.dpString)};${nl}`; // I3681 + } + } + } + + result += `${FTabStop}this.KVS=[${FOptionStores}];${nl}`; + + // Write the groups out + + // I853 - begin unicode missing causes crash + if (fk.StartGroup[KMXFile.BEGIN_UNICODE] == 0xFFFFFFFF) { + ReportError(0, CERR_InvalidBegin, 'A "begin unicode" statement is required to compile a KeymanWeb keyboard'); + return null; + } + + result += WriteBeginStatement('gs', fk.StartGroup[KMXFile.BEGIN_UNICODE]); + + rec := ExpandSentinel(PChar(sBegin_NewContext)); + if rec.Code = CODE_USE then + Result := Result + WriteBeginStatement('gn', rec.Use.GroupIndex); + rec := ExpandSentinel(PChar(sBegin_PostKeystroke)); + if rec.Code = CODE_USE then + Result := Result + WriteBeginStatement('gpk', rec.Use.GroupIndex); + + let fgp = source.keyboard.groups[fk.StartGroup[KMXFile.BEGIN_UNICODE]]; + result += + `${FTabStop}this.gs=function(t,e) {${nl}` + + `${FTabStop+FTabStop}return this.g${JavaScript_Name(fk.StartGroup[KMXFile.BEGIN_UNICODE], fgp.dpName)}(t,e);${nl}` + + `${FTabStop}}${nl}`; // I3681 + + for(let i = 0; i < source.keyboard.groups.length; i++) { // I1964 + let fgp = source.keyboard.groups[i]; + /* + Note on `r` and `m` variables in a group function: + + `m` can have one of three values: + 0: no rule from this group was matched + 1: a rule from this group was matched and did not include a `use` + statement + 2: a rule from this group matched and did include a `use` statement + (#5440) + + `m` is only used within a rule group to control the firing of the + `match` and `nomatch` rules. + + `r` can have one of two values: + 0: no rule from the final group matched (even if a rule from an + higher-level group did) + 1: a rule from the final group did match; + + `r` serves as the rule group's return value and is forwarded + recursively, best serving as a flag for whether or not default + output for a key should be emitted (0 means yes, emit the + default character output for that key). + */ + + result += + `${FTabStop}this.g${JavaScript_Name(i, fgp.dpName)}=function(t,e) {${nl}` + + `${FTabStop+FTabStop}var k=KeymanWeb,r=${fgp.fUsingKeys?0:1},m=0;${nl}`; //I1959 + + // fkp := fgp.dpKeyArray; + let HasRules = false; + + if (FFix183_LadderLength != 0) { + result += JavaScript_Rules(fgp); + } + else { + for (let j = 0; j < fgp.keys.length; j++) { // I1964 + let fkp = fgp.keys[j]; + if (!RuleIsExcludedByPlatform(fkp)) { + result += FTabstop+FTabstop; // I3681 + if (HasRules) { + result += 'else '; + } + HasRules = true; + + if (fgp.fUsingKeys) { + result += `if(k.KKM(e,${JavaScript_ShiftAsString(fkp, fMnemonic)},${JavaScript_KeyAsString(fkp, fMnemonic)})`; + } + + if (xstrlen(fkp.dpContext) > 0) { + result += fgp.fUsingKeys ? '&&' : 'if('; + result += JavaScript_ContextMatch(fkp, fkp.dpContext); + } + else if (!fgp.fUsingKeys) { + result += 'if(1'; + } + + linecomment = (fkp.Line > 0 && FDebug) ? ` // Line ${fkp.Line}` : ''; + + result += + `) {${linecomment}${nl}` + + FTabStop+FTabStop+FTabStop; + if (fgp.fUsingKeys) { // I1959 + result += 'r=m=1;' + JavaScript_OutputString(FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 + } + else { + result += 'm=1;' + JavaScript_OutputString(FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 + } + result += `${nl}${FTabStop}${FTabStop}}${nl}`; // I3681 + } + } + } + + if Assigned(fgp.dpMatch) then + Result := Result + Format( + '%sif(m==1) {%s'+ + '%s%s%s'+ + '%s}%s', + [FTabstop+FTabstop, nl, + FTabstop+Ftabstop, JavaScript_OutputString(FTabStop + FTabStop + FTabStop, nil, fgp.dpMatch, fgp), nl, + FTabstop+FTabstop, nl]); // I3681 + if Assigned(fgp.dpNoMatch) then + if fgp.fUsingKeys then // I1382 - fixup m=1 to m=g() + Result := Result + Format( + '%sif(!m&&k.KIK(e)) {%s'+ + '%sr=1;%s%s'+ + '%s}%s', + [FTabstop+FTabstop, nl, + FTabstop+FTabstop+FTabstop, JavaScript_OutputString(FTabStop + FTabStop + FTabStop, nil, fgp.dpNoMatch, fgp), nl, + FTabstop+FTabstop, nl]) // I1959. part 2, I2224 // I3681 + else + Result := Result + Format( + '%sif(!m) {%s'+ + '%s%s%s'+ + '%s}%s', + [FTabstop+FTabstop, nl, + FTabstop+FTabstop, JavaScript_OutputString(FTabStop + FTabStop + FTabStop, nil, fgp.dpNoMatch, fgp), nl, + FTabstop+FTabstop, nl]); // I1959 // I3681 + + Result := Result + Format('%sreturn r;%s'+ + '%s};%s', + [FTabstop+FTabstop, nl, + FTabstop, nl]); // I1959 // I3681 + Inc(fgp); + end; + + for n := 0 to FCallFunctions.Count - 1 do + begin + s := ExtractFilePath(FInFile) + FCallFunctions[n] + '.call_js'; + if FileExists(s) then + with TStringList.Create do + try + LoadFromFile(s, TEncoding.UTF8); // I3337 + Result := Result + Format('%sthis.c%d=function(t,e){%s};%s', [FTabstop, n, Trim(Text), nl]); // I3681 + finally + Free; + end + else + Result := Result + Format('%sthis.c%d=function(t,e){alert("call(%s) not defined");};%s', [FTabstop, n, FCallFunctions[n], nl]); // I3681 + end; + + Result := Result + sEmbedJS + '}' + nl; // I3681 +end; diff --git a/developer/src/kmc-kmw/src/main.ts b/developer/src/kmc-kmw/src/main.ts new file mode 100644 index 0000000000..742b9e4f47 --- /dev/null +++ b/developer/src/kmc-kmw/src/main.ts @@ -0,0 +1,2 @@ + +export { KeymanWebCompiler } from './compiler/keymanweb-compiler.js'; diff --git a/developer/src/kmc-kmw/src/util/util.ts b/developer/src/kmc-kmw/src/util/util.ts new file mode 100644 index 0000000000..d663fc490b --- /dev/null +++ b/developer/src/kmc-kmw/src/util/util.ts @@ -0,0 +1,7 @@ + +/** + * Verifies that value is an item in the enumeration. + */ +export function isValidEnumValue(enu: T, value: string) { + return (Object.values(enu) as string[]).includes(value); +} diff --git a/developer/src/kmc-kmw/tsconfig.json b/developer/src/kmc-kmw/tsconfig.json new file mode 100644 index 0000000000..a9dcdbbb2a --- /dev/null +++ b/developer/src/kmc-kmw/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../../tsconfig.esm-base.json", + + "compilerOptions": { + "outDir": "build/src/", + "rootDir": "src/", + "baseUrl": ".", + "allowSyntheticDefaultImports": true, // for ajv + + "paths": { + // "@keymanapp/keyman-version": ["../../../common/web/keyman-version/keyman-version.mts"], + "@keymanapp/common-types": ["../../../common/web/types/src/main"], + // "@keymanapp/": ["core/include/ldml/ldml-keyboard-constants"], + }, + + }, + "include": [ + "src/**/*.ts" + ], + "references": [ + { "path": "../../../common/web/keyman-version/tsconfig.esm.json" }, + { "path": "../../../common/web/types/" }, + { "path": "../../../core/include/ldml/"}, + ] +} diff --git a/developer/src/kmcmpdll/Compiler.cpp b/developer/src/kmcmpdll/Compiler.cpp index 8cc28d2ab7..89defad84d 100644 --- a/developer/src/kmcmpdll/Compiler.cpp +++ b/developer/src/kmcmpdll/Compiler.cpp @@ -319,6 +319,11 @@ int kmcmpMsgproc(int line, uint32_t dwMsgCode, char* szText, void* context) { } extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL ASaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc) // I4865 // I4866 +{ + return CompileKeyboardFileEx(pszInfile, pszOutfile, ASaveDebug, ACompilerWarningsAsErrors, AWarnDeprecatedCode, pMsgProc, CKF_KEYMAN); +} + +extern "C" BOOL __declspec(dllexport) CompileKeyboardFileEx(PSTR pszInfile, PSTR pszOutfile, BOOL ASaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc, int Target) // I4865 // I4866 { HANDLE hInfile = INVALID_HANDLE_VALUE, hOutfile = INVALID_HANDLE_VALUE; BOOL err; @@ -338,7 +343,7 @@ extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR p FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865 FWarnDeprecatedCode = AWarnDeprecatedCode; // I4866 - CompileTarget = CKF_KEYMAN; + CompileTarget = Target; if (!pMsgProc || !pszInfile || !pszOutfile) SetError(CERR_BadCallParams); diff --git a/developer/src/kmcomp/kmcomp.dproj b/developer/src/kmcomp/kmcomp.dproj index 36c16e3535..9bb6af3b5c 100644 --- a/developer/src/kmcomp/kmcomp.dproj +++ b/developer/src/kmcomp/kmcomp.dproj @@ -109,7 +109,7 @@ RELEASE;$(DCC_Define) - c:\temp\foo.kps -schema-path C:\Projects\keyman\app\common\schemas\kps\ + \Projects\keyman\keyboards\release\k\khmer_angkor\source\khmer_angkor.kmn c:\temp\ka.js true 2 1033 diff --git a/developer/src/tike/compile/CompileKeymanWeb.pas b/developer/src/tike/compile/CompileKeymanWeb.pas index 13d5219f70..e55966e5c3 100644 --- a/developer/src/tike/compile/CompileKeymanWeb.pas +++ b/developer/src/tike/compile/CompileKeymanWeb.pas @@ -275,6 +275,7 @@ uses System.TypInfo, CompileErrorCodes, + TempFileManager, JsonUtil, KeymanDeveloperOptions, Keyman.System.KeyboardUtils, @@ -282,6 +283,7 @@ uses kmxfileutils, TouchLayout, Unicode, + utilexecute, utilstr, VisualKeyboard, VKeys; @@ -303,6 +305,7 @@ function TCompileKeymanWeb.Compile(AOwnerProject: TProject; const InFile: string var WarnDeprecatedCode: Boolean; Data: string; + TempOutFile: TTempFile; begin FUnreachableKeys.Clear; @@ -337,9 +340,40 @@ begin WarnDeprecatedCode := True; end; + TempOutFile := TTempFileManager.Get('.kmx'); + GCallbackW := Callback; FCallFunctions := TStringList.Create; try + if CompileKeyboardFileEx(PChar(InFile), PChar(TempOutFile.Name), False, FCompilerWarningsAsErrors, + WarnDeprecatedCode, WebCompilerMessageA, CKF_KEYMANWEB) > 0 then + begin + if Assigned(AOwnerProject) and + Assigned(AOwnerProject.CompilerMessageFile) and + AOwnerProject.CompilerMessageFile.HasCompileWarning and + FCompilerWarningsAsErrors then + FError := True; + + if not FError then + begin + CopyFile(PChar(TempOutFile.Name), PChar(OutFile+'.kmx'), False); + // TODO: convert by calling node kmwc.js + // TODO: add +// TUtilExecute('node.exe kmwc.js "'+TempOutFile.Name+'" "'+OutFile+'"'); + {Data := WriteCompiledKeyboard; + + if not FError then + with TStringStream.Create(Data, TEncoding.UTF8) do + try + SaveToFile(OutFile); + finally + Free; + end;} + end; + + Result := not FError; // I1971 + +{ if CompileKeyboardFileToBuffer(PChar(InFile), @fk, FCompilerWarningsAsErrors, WarnDeprecatedCode, WebCompilerMessageA, CKF_KEYMANWEB) > 0 then // I3482 // I4866 // I4865 @@ -365,6 +399,7 @@ begin end; Result := not FError; // I1971 +} end else begin From dc05daefde7962b81fd78e374b979fe8d98b1c22 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 7 Dec 2022 19:56:30 +0700 Subject: [PATCH 02/21] feat: more work on compiler --- common/web/types/build.sh | 2 +- common/web/types/src/kmx/kmx.ts | 19 +- .../src/compiler/write-compiled-keyboard.ts | 185 ++++++++++++++++-- 3 files changed, 183 insertions(+), 23 deletions(-) diff --git a/common/web/types/build.sh b/common/web/types/build.sh index eb983acec8..0f2b408f1e 100755 --- a/common/web/types/build.sh +++ b/common/web/types/build.sh @@ -78,7 +78,7 @@ fi if builder_start_action test; then copy_schemas - npm test + npm test -- "${builder_extra_params[@]}" builder_finish_action success test fi diff --git a/common/web/types/src/kmx/kmx.ts b/common/web/types/src/kmx/kmx.ts index 2f47bddcdd..febda9b5e6 100644 --- a/common/web/types/src/kmx/kmx.ts +++ b/common/web/types/src/kmx/kmx.ts @@ -8,7 +8,20 @@ import * as r from 'restructure'; // kmx-builder will transform these to the corresponding COMP_xxxx export class KEYBOARD { - //TODO: additional header fields + fileVersion?: number; // dwFileVersion + keyboardVersion?: number; // version + + startGroup?: { + ansi: number; + unicode: number; + newContext: number; + postKeystroke: number; + }; + + flags?: number; + hotkey?: number; + + //bitmap: groups: GROUP[] = []; stores: STORE[] = []; }; @@ -328,6 +341,10 @@ export class KMXFile { public static readonly COMP_GROUP_SIZE = 24; public static readonly COMP_KEY_SIZE = 20; + + public static readonly VERSION_MASK_MINOR = 0x00FF; + public static readonly VERSION_MASK_MAJOR = 0xFF00; + /* In-memory representation of the keyboard */ public keyboard: KEYBOARD = { diff --git a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts index 603b2be784..2d4b061d56 100644 --- a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts +++ b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts @@ -4,9 +4,35 @@ function requote(s: string): string { return "'" + s.replaceAll(/(['\\])/, "\\$1") + "'"; } -export function WriteCompiledKeyboard(source: KMXFile): string { +function RequotedString(s: string, RequoteSingleQuotes: boolean = false): string { + // TODO: use a JSON encode + let i: number = 0; + while(i < s.length) { + if (s.charAt(i) == '"' || s.charAt(i) == '\\') { + s = s.substring(0, i) + '\\' + s.substring(i); + i++; + } + else if (s.charAt(i) == '\'' && RequoteSingleQuotes) { + s = s.substring(0, i) + '\\' + s.substring(i); + i++; + } + else if(s.charAt(i) == '\n') { + s = s.substring(0, i) + '\\n' + s.substring(i + 1); + } + else if(s.charAt(i) == '\r') { + s = s.substring(0, i) + ' ' + s.substring(i + 1); + } + } + return s; +} + +export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boolean = false): string { + let nl = FDebug ? '\n' : ''; + let FTabStop = FDebug ? ' ' : ''; + // let fgp: GROUP; - let fsp: STORE; + + let fsp: STORE; let fkp: KEY; let j: number; @@ -70,7 +96,7 @@ export function WriteCompiledKeyboard(source: KMXFile): string { } } - const sName = 'Keyboard_'+TKeyboardUtils.GetKeymanWebCompiledNameFromFileName(FInFile); + const sName = 'Keyboard_'+name; //TODO: verify --> GetKeymanWebCompiledNameFromFileName(FInFile); if (sHelpFile != '') { sHelp = ''; @@ -183,13 +209,9 @@ export function WriteCompiledKeyboard(source: KMXFile): string { sVisualKeyboard = 'null'; } - sModifierBitmask = GetKeyboardModifierBitmask; - - fMnemonic = vMnemonic == 1; - - let nl = '';//TODO - let FTabStop = '';//TODO + sModifierBitmask = GetKeyboardModifierBitmask(source); + const fMnemonic = vMnemonic == 1; result += `${JavaScript_SetupProlog}${nl}` + @@ -201,8 +223,8 @@ export function WriteCompiledKeyboard(source: KMXFile): string { // Following line caches the Keyman major version `${FTabStop}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` + `${FTabStop}this.KI="${sName}";${nl}` + - `${FTabStop}this.KN="%s";${nl}` + , RequotedString(sFullName), nl, - `${FTabStop}this.KMINVER="${(fk.version & VERSION_MASK_MAJOR) >> 8}.${fkp.version & VERSION_MASK_MINOR}";${nl}` + + `${FTabStop}this.KN="${RequotedString(sFullName)}";${nl}`, nl, + `${FTabStop}this.KMINVER="${(source.keyboard.fileVersion & KMXFile.VERSION_MASK_MAJOR) >> 8}.${source.keyboard.fileVersion & KMXFile.VERSION_MASK_MINOR}";${nl}` + `${FTabStop}this.KV=${sVisualKeyboard};${nl}` + `${FTabStop}this.KDU=${fDisplayUnderlying?'1':'0'};${nl}` + `${FTabStop}this.KH=${sHelp};${nl}` + @@ -211,7 +233,7 @@ export function WriteCompiledKeyboard(source: KMXFile): string { `${FTabStop}this.KMBM=${sModifierBitmask};${nl}` + `${sRTL}`; // I3681 - if (HasSupplementaryPlaneChars) { + if (HasSupplementaryPlaneChars()) { result += `${FTabStop}this.KS=1;${nl}`; } @@ -267,19 +289,21 @@ export function WriteCompiledKeyboard(source: KMXFile): string { return null; } - result += WriteBeginStatement('gs', fk.StartGroup[KMXFile.BEGIN_UNICODE]); + result += WriteBeginStatement('gs', source.keyboard.startGroup.unicode); - rec := ExpandSentinel(PChar(sBegin_NewContext)); - if rec.Code = CODE_USE then - Result := Result + WriteBeginStatement('gn', rec.Use.GroupIndex); - rec := ExpandSentinel(PChar(sBegin_PostKeystroke)); - if rec.Code = CODE_USE then - Result := Result + WriteBeginStatement('gpk', rec.Use.GroupIndex); + let rec = ExpandSentinel(sBegin_NewContext); + if(rec.Code == CODE_USE) { + result += WriteBeginStatement('gn', rec.Use.GroupIndex); + } + rec = ExpandSentinel(sBegin_PostKeystroke); + if(rec.Code == CODE_USE) { + result += WriteBeginStatement('gpk', rec.Use.GroupIndex); + } - let fgp = source.keyboard.groups[fk.StartGroup[KMXFile.BEGIN_UNICODE]]; + let fgp = source.keyboard.groups[source.keyboard.startGroup.unicode]; result += `${FTabStop}this.gs=function(t,e) {${nl}` + - `${FTabStop+FTabStop}return this.g${JavaScript_Name(fk.StartGroup[KMXFile.BEGIN_UNICODE], fgp.dpName)}(t,e);${nl}` + + `${FTabStop+FTabStop}return this.g${JavaScript_Name(source.keyboard.startGroup.unicode, fgp.dpName)}(t,e);${nl}` + `${FTabStop}}${nl}`; // I3681 for(let i = 0; i < source.keyboard.groups.length; i++) { // I1964 @@ -406,3 +430,122 @@ export function WriteCompiledKeyboard(source: KMXFile): string { Result := Result + sEmbedJS + '}' + nl; // I3681 end; +} + +/// +/// Determine the modifiers used in the target keyboard and return a bitmask +/// representing them, or an integer value when not in debug mode +/// +/// @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 */' +/// +function GetKeyboardModifierBitmask(source: KMXFile): string { + let bitMask = 0; + for(let gp of source.keyboard.groups) { + if(gp.fUsingKeys) { + for(let kp of gp.keys) { + if(!RuleIsExcludedByPlatform(kp)) { + bitMask |= JavaScript_Shift(kp, fMnemonic); + } + } + } + } + + if ((bitMask & KMXFile.KMX_MASK_MODIFIER_CHIRAL) && (bitMask & KMXFile.KMX_MASK_MODIFIER_NONCHIRAL)) { + ReportError(0, CWARN_DontMixChiralAndNonChiralModifiers, 'This keyboard contains Ctrl,Alt and LCtrl,LAlt,RCtrl,RAlt sets of modifiers. Use only one or the other set for web target.'); + } + + if(FDebug) { + return FormatModifierAsBitflags(bitMask & KMXFile.KMX_MASK_KEYS); // Exclude KMX_ISVIRTUALKEY, KMX_VIRTUALCHARKEY + } + + return '0x'+(bitMask & KMXFile.KMX_MASK_KEYS).toString(16); +} + + +/// +/// If debug mode, then returns Javascript code necessary for +/// accessing constants in the compiled keyboard +/// +/// @return string of JavaScript code +/// +function JavaScript_SetupDebug() { + if(IsKeyboardVersion10OrLater()) { + if(FDebug) { + return 'var modCodes = keyman.osk.modifierCodes;'+nl+ + FTabStop+'var keyCodes = keyman.osk.keyCodes;'+nl; + } + } + return ''; +} + +function JavaScript_SetupProlog() { + if(IsKeyboardVersion10OrLater()) { + return 'if(typeof keyman === \'undefined\') {'+nl+ + FTabStop+'console.log(\'Keyboard requires KeymanWeb 10.0 or later\');'+nl+ + FTabStop+'if(typeof tavultesoft !== \'undefined\') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later");'+nl+ + '} else {'; + } + return ''; +} + +function JavaScript_SetupEpilog() { + if(IsKeyboardVersion10OrLater()) { + return '}'; + } + return ''; +} + +function HasSupplementaryPlaneChars() { + return false; // TODO +/* function StringHasSuppChars(p: PWideChar): Boolean; + begin + if not Assigned(p) then + Exit(False); + + while p^ <> #0 do + begin + if Char.IsSurrogate(p, 0) then + Exit(True); + p := incxstr(p); + end; + + Result := False; + end; + +var + I: Integer; + fsp: PFILE_STORE; + fgp: PFILE_GROUP; + j: Integer; + fkp: PFILE_KEY; +begin + fsp := fk.dpStoreArray; + for i := 0 to Integer(fk.cxStoreArray) - 1 do + begin + if StringHasSuppChars(fsp.dpString) then + Exit(True); + Inc(fsp); + end; + + fgp := fk.dpGroupArray; + for i := 0 to Integer(fk.cxGroupArray) - 1 do + begin + fkp := fgp.dpKeyArray; + for j := 0 to Integer(fgp.cxKeyArray) - 1 do + begin + if StringHasSuppChars(fkp.dpContext) or + StringHasSuppChars(fkp.dpOutput) then + Exit(True); + Inc(fkp); + end; + + if StringHasSuppChars(fgp.dpMatch) or + StringHasSuppChars(fgp.dpNoMatch) then + Exit(True); + + Inc(fgp); + end; + + Result := False; +end;*/ +} \ No newline at end of file From f68a4c84fdb41d1a9e8d1beff2ef636b78b13f54 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 19 Dec 2022 14:35:24 +1100 Subject: [PATCH 03/21] chore: continue --- .../src/kmc-kmw/src/compiler/callbacks.ts | 1 + .../kmc-kmw/src/compiler/compiler-globals.ts | 28 ++ .../src/compiler/javascript-strings.ts | 327 ++++++++++++++++++ .../src/compiler/keymanweb-compiler.ts | 15 +- .../src/kmc-kmw/src/compiler/messages.ts | 306 +++++++++++----- .../src/compiler/write-compiled-keyboard.ts | 95 +++-- 6 files changed, 624 insertions(+), 148 deletions(-) create mode 100644 developer/src/kmc-kmw/src/compiler/compiler-globals.ts create mode 100644 developer/src/kmc-kmw/src/compiler/javascript-strings.ts diff --git a/developer/src/kmc-kmw/src/compiler/callbacks.ts b/developer/src/kmc-kmw/src/compiler/callbacks.ts index f6cd673b56..c20a2b078c 100644 --- a/developer/src/kmc-kmw/src/compiler/callbacks.ts +++ b/developer/src/kmc-kmw/src/compiler/callbacks.ts @@ -1,4 +1,5 @@ export interface CompilerEvent { + line: number; code: number; message: string; }; diff --git a/developer/src/kmc-kmw/src/compiler/compiler-globals.ts b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts new file mode 100644 index 0000000000..f769c768ba --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts @@ -0,0 +1,28 @@ +import { KEYBOARD, KMXFile } from "@keymanapp/common-types/src/kmx/kmx"; +import CompilerOptions from "./compiler-options.js"; + +export let FTabStop: string; +export let nl: string; +export let FCompilerWarningsAsErrors = false; +export let fk: KEYBOARD; +export let FMnemonic: boolean; +export let options: CompilerOptions; + +export function setupGlobals(_options: CompilerOptions, _tab: string, _nl: string, _keyboard: KEYBOARD) { + options = _options; + FTabStop = _tab; + nl = _nl; + fk = _keyboard; +} + +export function IsKeyboardVersion10OrLater(): boolean { + return fk.fileVersion >= KMXFile.VERSION_100; +} + +export function IsKeyboardVersion14OrLater(): boolean { + return fk.fileVersion >= KMXFile.VERSION_140; +} + +export function IsKeyboardVersion15OrLater(): boolean { + return fk.fileVersion >= KMXFile.VERSION_150; +} diff --git a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts new file mode 100644 index 0000000000..8b95d484f0 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts @@ -0,0 +1,327 @@ +import { GROUP, KEY, KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; + +import { FMnemonic, FTabStop, IsKeyboardVersion10OrLater, nl, options } from "./compiler-globals.js"; +import { CERR_VirtualCharacterKeysNotSupportedInKeymanWeb, CERR_VirtualKeysNotValidForMnemonicLayouts, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, CWARN_OptionStoreNameInvalid, ReportError } from "./messages.js"; + +//const SValidIdentifierCharSet = '123'; + +export function JavaScript_Name(i: number, pwszName: string, KeepNameForPersistentStorage: boolean = false): string { // I3659 + let FChanged: boolean = false; + let p = pwszName; + + if((pwszName == null || pwszName == undefined || pwszName == '') || (!isFDebug && !KeepNameForPersistentStorage)) { // I3659 // I3681 + return i.toString(10); // for uniqueness + } + else { + let result = KeepNameForPersistentStorage // I3659 + ? '' // Potential for overlap in theory but in practice we only use this for named option stores so can never overlap + : '_'; // Ensures we cannot overlap numbered instances + while(p.length) { + let ch = p.charAt(0); + if(SValidIdentifierCharSet.includes(ch)) { // I3681 + result += ch; + } else { + result += '_'; + FChanged = true; + } + p = p.substring(1); + } + if(!KeepNameForPersistentStorage) { + // Ensure each transformed name is still unique + result += '_' + i.toString(10); + if(FChanged) { + result += '/*'+pwszName.replace(/\*\//g, '*-/')+'*/'; + } + } else if(FChanged) { + // For named option stores, we are only supporting the valid identifier + // character set, which is a breaking change in 14.0. + ReportError(0, CWARN_OptionStoreNameInvalid, + Format('The option store %s should be named with characters in the range A-Z, a-z, 0-9 and _ only.', + [pwszName])); + } + return result; + } +} + +export function JavaScript_Store(line: number, pwsz: string): string { + let ch: number, rec: TSentinelRecord, result: string; + const wcsentinel: string = '\uFFFF'; + let n = pwsz.indexOf(wcsentinel); + + // Start: plain text store. Always use for < 10.0, conditionally for >= 10.0. + if(n == 0 || !IsKeyboardVersion10OrLater) { + result = '"'; + while(pwsz.length) { + if(pwsz.charCodeAt(0) == KMXFile.UC_SENTINEL) { + result += '.'; // UC_SENTINEL values are not supported in stores for KMW < 10.0. + } else { + ch = GetSuppChar(pwsz); + if(ch == '"' || ch == '\\') { + result += '\\'; + } + result += JavaScript_String(ch); // I2242 + } + + pwsz = pwsz.substring(1); + } + result += '"'; + } + else { + result = '['; + while(pwsz.length) { + if(result != '[') { + result += ','; + } + rec = ExpandSentinel(pwsz); + if(rec.IsSentinel) { + if(rec.Code == KMXFile.CODE_DEADKEY) { + result += `{t:'d',d:${rec.Deadkey.DeadKey}}`; + } + else if(rec.Code == KMXFile.CODE_BEEP) { + result += `{t:'b'}`; + } + else { //if rec.Code = CODE_EXTENDED then + // At some point, we may wish to filter which codes are safe to stub out like this + // versus which ones should be an error. The commented-out-code shows the way to + // handle such cases. + result += `''`; + } +// else +// begin +// //ReportError(line, CERR_SomewhereIGotItWrong, 'Internal Error: unexpected sentinel character in store definition'); +// end; + } + else { + ch = GetSuppChar(pwsz); + result += '"'; + // TODO: Refactor the section below into JavaScript_String, as it's + // quite common in our code base. + if(ch == '"'.charCodeAt(0) || ch == '\\'.charCodeAt(0)) { + result += '\\'; + } + result += JavaScript_String(ch) + '"'; // I2242 + } + + pwsz = pwsz.substring(1); + } + result += ']'; + } + return result; +} + +export function JavaScript_String(ch: number): string { // I2242 + if(ch < 32) { + switch(ch) { + case 9: return '\\t'; + case 10: return '\\n'; + case 13: return '\\r'; + } + if(ch < 9) { + return '\\x0'+ch.toString(16); + } else { + return '\\x'+ch.toString(16); + } + } + else { + return String.fromCodePoint(ch); + } +} + +export function JavaScript_Rules(fgp: GROUP): string { + let IsEqualKey = function(k1: KEY, k2: KEY): boolean { + return ( + (JavaScript_Key(k1, FMnemonic) == JavaScript_Key(k2, FMnemonic)) && + (JavaScript_Shift(k1, FMnemonic) == JavaScript_Shift(k2, FMnemonic)) + ); + } + + let result = ''; + let HasRules = false; + + let processed_rule = Array(fgp.keys.length); + for(let j = 0; j < fgp.keys.length; j++) { + processed_rule[j] = false; + } + + let j = 0; + let Counter = 0; + while(j < fgp.keys.length) { // I1964 + if(!processed_rule[j] && !RuleIsExcludedByPlatform(fkp)) { + let fkp = fgp.keys[j]; + // Break down by key code + // We know the rules are sorted by context length and then key code. + // First pass, break the grouping down by key code. + + if(fgp.fUsingKeys) { + result += + `${FTabStop+FTabStop}${HasRules?'else ':''}`+ + `if(k.KKM(e,${JavaScript_ShiftAsString(fkp, fMnemonic)},${JavaScript_KeyAsString(fkp, fMnemonic)})) {${nl}`; + + HasRules = true; + Counter++; + + let LocalHasRules = false; + let fkp2 = fgp.keys[j]; + let j2 = j; + let LocalCounter = 0; + while (j < fgp.keys.length) { + fkp = fgp.keys[j]; + if (!processed_rule[j] && !RuleIsExcludedByPlatform(fkp) && IsEqualKey(fkp, fkp2)) { + processed_rule[j] = true; + result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, LocalHasRules ? 'else ' : '', fgp, fkp); + LocalCounter++; + + if (FFix183_LadderLength != 0 && (LocalCounter % FFix183_LadderLength) == 0) { + // Break if/else ladders + result += `${FTabStop+FTabStop+FTabStop}if(m) {}${nl}`; + } + LocalHasRules = true; + } + + j++; + } + + result += FTabStop + FTabStop + '}' + nl; + j = j2 + 1; + } + else { + // TODO: context character level switches instead of full context comparisons + result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, HasRules ? 'else ' : '', fgp, fkp); + HasRules = true; + Counter++; + j++; + } + + if (FFix183_LadderLength != 0 && (Counter % FFix183_LadderLength) == 0) { + // Break if/else ladders + // We need to only match if no previous line is matched (i.e. m is false) + result += `${FTabStop+FTabStop+FTabStop}if(m) {}${nl}`; + } + } + else { + j++; + } + } + return result; +} + +export function JavaScript_Shift(fkp: KEY, FMnemonic: boolean): number { + if (FMnemonic) { + if (fkp.ShiftFlags & KMXFile.VIRTUALCHARKEY) { + ReportError(fkp.Line, CERR_VirtualCharacterKeysNotSupportedInKeymanWeb, 'Virtual character keys not currently supported in KeymanWeb'); // I1971 // I4061 + return 0; + } + + if (fkp.ShiftFlags & KMXFile.ISVIRTUALKEY && fkp.Key <= 255) { + // We prohibit K_ keys for mnemonic layouts. We don't block T_ and U_ keys. + // TODO: this doesn't resolve the issue of, e.g. SHIFT+K_SPACE + // https://github.com/keymanapp/keyman/issues/265 + ReportError(fkp.Line, CERR_VirtualKeysNotValidForMnemonicLayouts, 'Virtual keys are not valid for mnemonic layouts'); // I1971 // I4061 + return 0; + } + } + + if (fkp.ShiftFlags & KMXFile.ISVIRTUALKEY) { + if(IsKeyboardVersion10OrLater()) { + // Full chiral modifier and state key support starts with KeymanWeb 10.0 + return fkp.ShiftFlags; + } + + // Non-chiral support only and no support for state keys + if (fkp.ShiftFlags & (KMXFile.LCTRLFLAG | KMXFile.RCTRLFLAG | KMXFile.LALTFLAG | KMXFile.RALTFLAG)) { // I4118 + ReportError(fkp.Line, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, 'Extended shift flags LALT, RALT, LCTRL, RCTRL are not supported in KeymanWeb'); + } + + if (fkp.ShiftFlags & ( + KMXFile.CAPITALFLAG | KMXFile.NOTCAPITALFLAG | KMXFile.NUMLOCKFLAG | KMXFile.NOTNUMLOCKFLAG | + KMXFile.SCROLLFLAG | KMXFile.NOTSCROLLFLAG)) { // I4118 + ReportError(fkp.Line, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, 'Extended shift flags CAPS and NCAPS are not supported in KeymanWeb'); + } + + return KMXFile.ISVIRTUALKEY | (fkp.ShiftFlags & (KMXFile.K_SHIFTFLAG | KMXFile.K_CTRLFLAG | KMXFile.K_ALTFLAG)); + } + + return USEnglishShift.includes(fkp.Key) ? KMXFile.ISVIRTUALKEY | KMXFile.K_SHIFTFLAG : KMXFile.ISVIRTUALKEY; +} + +/** + * Returns a Javascript representation of a key modifier state, either as a constant (debug mode) + * or as an integer. + * + * @param fkp Pointer to key record + * @param FMnemonic True if the keyboard is a mnemonic layout + * + * @return string representation of the key modifier state, e.g. + * 'modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 * /' or + * '16656' + */ +export function JavaScript_ShiftAsString(fkp: KEY, FMnemonic: boolean): string { + if(!options.debug) { + return JavaScript_Shift(fkp, FMnemonic).toString(); + } + return ' '+FormatModifierAsBitflags(JavaScript_Shift(fkp, FMnemonic)); +} + + + +function TCompileKeymanWeb.JavaScript_Key(fkp: PFILE_KEY; FMnemonic: Boolean): Integer; +var + n: Integer; + i: Integer; +begin + if not FMnemonic then + begin + if (fkp.ShiftFlags and KMX_ISVIRTUALKEY) = KMX_ISVIRTUALKEY then + begin + Result := Ord(fkp.Key); + end + else + begin + // Convert the character to a virtual key + n := Pos(fkp.Key, USEnglishShift); + if n = 0 then n := Pos(fkp.Key, USEnglishUnshift); + if n = 0 + then Result := 0 + else Result := Ord(USEnglishValues[n]); + end; + end + else + begin + Result := Ord(fkp.Key); + end; + + // Check that key is not unreachable (e.g. K_SHIFT, touch-specific special keys 50,000+) + + for i := 0 to High(UnreachableKeyCodes) do // I4141 + if Result = UnreachableKeyCodes[i] then + Result := 0; + + if (Result = 0) or (Result >= Ord(Low(TKeymanWebTouchStandardKey))) then // I4141 + begin + if not FUnreachableKeys.Contains(fkp) then + begin + ReportError(fkp.Line, CHINT_UnreachableKeyCode, + 'The rule will never be matched for key '+ + FormatKeyForErrorMessage(fkp,FMnemonic)+' because its key code is never fired.'); + FUnreachableKeys.Add(fkp); + end; + end; +end; + +/// +/// Returns a Javascript representation of a key value, either as a constant (debug mode) +/// or as an integer. +/// +/// @param fkp Pointer to key record +/// @param FMnemonic True if the keyboard is a mnemonic layout +/// +/// @return string representation of the key value, e.g. 'keyCodes.K_A /* 0x41 */' or '65' +/// +function JavaScript_KeyAsString(fkp: KEY, FMnemonic: boolean): string { + if(options.debug) { + return ' '+FormatKeyAsString(JavaScript_Key(fkp, FMnemonic)); + } else { + return JavaScript_Key(fkp, FMnemonic).toString(); + } +} + diff --git a/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts b/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts index 03fc953e3f..1b162b738a 100644 --- a/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts +++ b/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts @@ -1,22 +1,21 @@ import { VisualKeyboard } from "@keymanapp/common-types"; - import * as path from 'path'; -import { KMXFile } from "../../../../../common/web/types/src/kmx/kmx"; -// import VisualKeyboardCompiler from "./visual-keyboard-compiler.js"; -export interface KeymanWebCompilerOptions { - debug?: boolean; -}; +import { KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; +// import VisualKeyboardCompiler from "./visual-keyboard-compiler.js"; +import { nl, FTabStop, setupGlobals } from "./compiler-globals.js"; +import CompilerOptions from "./compiler-options.js"; export class KeymanWebCompiler { - private readonly options: KeymanWebCompilerOptions; + private readonly options: CompilerOptions; private readonly nl: string; private readonly tab: string; - constructor(options?: KeymanWebCompilerOptions) { + constructor(options?: CompilerOptions) { this.options = options; this.nl = this.options.debug ? "\n" : ''; this.tab = this.options.debug ? " " : ''; + setupGlobals(this.options, this.tab, this.nl); } public compile(name: string, source: KMXFile): string { diff --git a/developer/src/kmc-kmw/src/compiler/messages.ts b/developer/src/kmc-kmw/src/compiler/messages.ts index 0a6801f9d2..9f443cfc0d 100644 --- a/developer/src/kmc-kmw/src/compiler/messages.ts +++ b/developer/src/kmc-kmw/src/compiler/messages.ts @@ -1,97 +1,219 @@ +import { FCompilerWarningsAsErrors } from "./compiler-globals.js"; -export enum CompilerErrorSeverity { - Info = 0x000000, - Hint = 0x100000, - Warn = 0x200000, - Error = 0x300000, - Fatal = 0x400000, - Severity_Mask = 0xF00000, // includes reserved bits - Error_Mask = 0x0FFFFF, -}; +export let FError = false; -const m = (code: number, message: string) => { return { code, message } }; -const SevInfo = CompilerErrorSeverity.Info; -const SevHint = CompilerErrorSeverity.Hint; -// const SevWarn = CompilerErrorSeverity.Warn; -const SevError = CompilerErrorSeverity.Error; -const SevFatal = CompilerErrorSeverity.Fatal; - -export class CompilerMessages { - static Error_InvalidNormalization = (o:{form: string}) => m(this.ERROR_InvalidNormalization, `Invalid normalization form '${o.form}`); - static ERROR_InvalidNormalization = SevError | 0x0001; - - static Error_InvalidLocale = (o:{tag: string}) => m(this.ERROR_InvalidLocale, `Invalid BCP 47 locale form '${o.tag}'`); - static ERROR_InvalidLocale = SevError | 0x0002; - - static Error_HardwareLayerHasTooManyRows = () => m(this.ERROR_HardwareLayerHasTooManyRows, `'hardware' layer has too many rows`); - static ERROR_HardwareLayerHasTooManyRows = SevError | 0x0003; - - static Error_RowOnHardwareLayerHasTooManyKeys = (o:{row: number}) => m(this.ERROR_RowOnHardwareLayerHasTooManyKeys, `Row #${o.row} on 'hardware' layer has too many keys`); - static ERROR_RowOnHardwareLayerHasTooManyKeys = SevError | 0x0004; - - static Error_KeyNotFoundInKeyBag = (o:{keyId: string, col: number, row: number, layer: string, form: string}) => - m(this.ERROR_KeyNotFoundInKeyBag, `Key '${o.keyId}' in position #${o.col} on row #${o.row} of layer ${o.layer}, form '${o.form}' not found in key bag`); - static ERROR_KeyNotFoundInKeyBag = SevError | 0x0005; - - static Hint_OneOrMoreRepeatedLocales = () => - m(this.HINT_OneOrMoreRepeatedLocales, `After minimization, one or more locales is repeated and has been removed`); - static HINT_OneOrMoreRepeatedLocales = SevHint | 0x0006; - - static Error_InvalidFile = (o:{errorText: string}) => - m(this.ERROR_InvalidFile, `The source file has an invalid structure: ${o.errorText}`); - static ERROR_InvalidFile = SevError | 0x0007; - - static Hint_LocaleIsNotMinimalAndClean = (o:{sourceLocale: string, locale: string}) => - m(this.HINT_LocaleIsNotMinimalAndClean, `Locale '${o.sourceLocale}' is not minimal or correctly formatted and should be '${o.locale}'`); - static HINT_LocaleIsNotMinimalAndClean = SevHint | 0x0008; - - static Error_VkeyIsNotValid = (o:{vkey: string}) => - m(this.ERROR_VkeyIsNotValid, `Virtual key '${o.vkey}' is not found in the CLDR VKey Enum table.`); - static ERROR_VkeyIsNotValid = SevError | 0x0009; - - static Hint_VkeyIsRedundant = (o:{vkey: string}) => - m(this.HINT_VkeyIsRedundant, `Virtual key '${o.vkey}' is mapped to itself, which is redundant.`); - static HINT_VkeyIsRedundant = SevHint | 0x000A; - - static Error_VkeyIsRepeated = (o:{vkey: string}) => - m(this.ERROR_VkeyIsRepeated, `Virtual key '${o.vkey}' has more than one vkey entry.`); - static ERROR_VkeyIsRepeated = SevError | 0x000B; - - static Info_MultipleVkeysHaveSameTarget = (o:{vkey: string}) => - m(this.INFO_MultipleVkeysHaveSameTarget, `Target virtual key '${o.vkey}' has multiple source mappings, which may be an error.`); - static INFO_MultipleVkeysHaveSameTarget = SevInfo | 0x000C; - - static Error_InvalidVersion = (o:{version: string}) => - m(this.ERROR_InvalidVersion, `Version number '${o.version}' must be a semantic version format string.`); - static ERROR_InvalidVersion = SevError | 0x000D; - - static Error_MustBeAtLeastOneLayerElement = () => - m(this.ERROR_MustBeAtLeastOneLayerElement, `The source file must contain at least one layer element.`); - static ERROR_MustBeAtLeastOneLayerElement = SevError | 0x000E; - - static Fatal_SectionCompilerFailed = (o:{sect: string}) => - m(this.FATAL_SectionCompilerFailed, `The compiler for '${o.sect}' failed unexpectedly.`); - static FATAL_SectionCompilerFailed = SevFatal | 0x000F; - - static Error_DisplayIsRepeated = (o:{to: string}) => - m(this.ERROR_DisplayIsRepeated, `display to='${o.to}' has more than one display entry.`); - static ERROR_DisplayIsRepeated = SevError | 0x0010; - - static Error_KeyMissingToGapOrSwitch = (o:{keyId: string}) => - m(this.ERROR_KeyMissingToGapOrSwitch, `key id='${o.keyId}' must have either to=, gap=, or switch=.`); -static ERROR_KeyMissingToGapOrSwitch = SevError | 0x0011; - - static severityName(code: number): string { - let severity = code & CompilerErrorSeverity.Severity_Mask; - switch(severity) { - case CompilerErrorSeverity.Info: return 'INFO'; - case CompilerErrorSeverity.Hint: return 'HINT'; - case CompilerErrorSeverity.Warn: return 'WARN'; - case CompilerErrorSeverity.Error: return 'ERROR'; - case CompilerErrorSeverity.Fatal: return 'FATAL'; - /* istanbul ignore next */ - default: return 'UNKNOWN'; - } +export function ReportError(line: number, msgcode: number, text: string) { // I1971 + let flag = CERR_FLAG | CFATAL_FLAG; + if(FCompilerWarningsAsErrors) { + flag |= CWARN_FLAG; } + if (msgcode & flag) { + FError = true; + } + FCallback(line, msgcode, text); // I3310 } +export const + CHINT_FLAG = 0x1000, + CWARN_FLAG = 0x2000, + CERR_FLAG = 0x4000, + CFATAL_FLAG = 0x8000, + +// Any messages from the lexical model compiler occupy this range: + CERR_LEXICAL_MODEL_MIN = 0x0800, + CERR_LEXICAL_MODEL_MAX = 0x08FF, + + CERR_None = 0x0000, + CERR_EndOfFile = 0x0001, + + CERR_BadCallParams = 0x8002, + CERR_CannotAllocateMemory = 0x9004, + CERR_InfileNotExist = 0x8005, + CERR_CannotCreateOutfile = 0x8006, + CERR_UnableToWriteFully = 0x8007, + CERR_CannotReadInfile = 0x8008, + CERR_SomewhereIGotItWrong = 0x8009, + + CERR_InvalidToken = 0x400A, + CERR_InvalidBegin = 0x400B, + CERR_InvalidName = 0x400C, + CERR_InvalidVersion = 0x400D, + CERR_InvalidLanguageLine = 0x400E, + CERR_LayoutButNoLanguage = 0x400F, + CERR_InvalidLayoutLine = 0x4010, + CERR_NoVersionLine = 0x4011, + CERR_InvalidGroupLine = 0x4012, + CERR_InvalidStoreLine = 0x4013, + CERR_InvalidCodeInKeyPartOfRule = 0x4014, + CERR_InvalidDeadkey = 0x4015, + CERR_InvalidValue = 0x4016, + CERR_ZeroLengthString = 0x4017, + CERR_TooManyIndexToKeyRefs = 0x4018, + CERR_UnterminatedString = 0x4019, + CERR_StringInVirtualKeySection = 0x401A, + CERR_AnyInVirtualKeySection = 0x401B, + CERR_InvalidAny = 0x401C, + CERR_StoreDoesNotExist = 0x401D, + CERR_BeepInVirtualKeySection = 0x401E, + CERR_IndexInVirtualKeySection = 0x401F, + CERR_InvalidIndex = 0x4020, + CERR_OutsInVirtualKeySection = 0x4021, + CERR_InvalidOuts = 0x4022, + CERR_ContextInVirtualKeySection = 0x4024, + CERR_InvalidUse = 0x4025, + CERR_GroupDoesNotExist = 0x4026, + CERR_VirtualKeyNotAllowedHere = 0x4027, + CERR_InvalidSwitch = 0x4028, + CERR_NoTokensFound = 0x4029, + CERR_InvalidLineContinuation = 0x402A, + CERR_LineTooLong = 0x402B, + CERR_InvalidCopyright = 0x402C, + CERR_CodeInvalidInThisSection = 0x402D, + CERR_InvalidMessage = 0x402E, + CERR_InvalidLanguageName = 0x402F, + CERR_InvalidBitmapLine = 0x4030, + CERR_CannotReadBitmapFile = 0x4031, + CERR_IndexDoesNotPointToAny = 0x4032, + CERR_ReservedCharacter = 0x4033, + CERR_InvalidCharacter = 0x4034, + CERR_InvalidCall = 0x4035, + CERR_CallInVirtualKeySection = 0x4036, + CERR_CodeInvalidInKeyStore = 0x4037, + CERR_CannotLoadIncludeFile = 0x4038, + + CERR_60FeatureOnly_EthnologueCode = 0x4039, + CERR_60FeatureOnly_MnemonicLayout = 0x403A, + CERR_60FeatureOnly_OldCharPosMatching = 0x403B, + CERR_60FeatureOnly_NamedCodes = 0x403C, + CERR_60FeatureOnly_Contextn = 0x403D, + CERR_501FeatureOnly_Call = 0x403E, + + CERR_InvalidNamedCode = 0x403F, + CERR_InvalidSystemStore = 0x4040, + + CERR_CallIsProfessionalFeature = 0x4041, + CERR_IncludeCodesIsProfessionalFeature = 0x4042, + CERR_MnemonicLayoutIsProfessionalFeature = 0x4043, + CERR_60FeatureOnly_VirtualCharKey = 0x4044, + + CERR_VersionAlreadyIncluded = 0x4045, + + CERR_70FeatureOnly = 0x4046, + + CERR_80FeatureOnly = 0x4047, + CERR_InvalidInVirtualKeySection = 0x4048, + CERR_InvalidIf = 0x4049, + CERR_InvalidReset = 0x404A, + CERR_InvalidSet = 0x404B, + CERR_InvalidSave = 0x404C, + + CERR_InvalidEthnologueCode = 0x404D, + + CERR_CannotCreateTempfile = 0x804E, + + CERR_90FeatureOnly_IfSystemStores = 0x404F, + CERR_IfSystemStore_NotFound = 0x4050, + CERR_90FeatureOnly_SetSystemStores = 0x4051, + CERR_SetSystemStore_NotFound = 0x4052, + CERR_90FeatureOnlyVirtualKeyDictionary = 0x4053, + + CERR_NotSupportedInKeymanWebContext = 0x4054, + CERR_NotSupportedInKeymanWebOutput = 0x4055, + CERR_NotSupportedInKeymanWebStore = 0x4056, + CERR_VirtualCharacterKeysNotSupportedInKeymanWeb = 0x4057, + CERR_VirtualKeysNotValidForMnemonicLayouts = 0x4058, + CERR_InvalidTouchLayoutFile = 0x4059, + CERR_TouchLayoutInvalidIdentifier = 0x405A, // I4142 + CERR_InvalidKeyCode = 0x405B, // I4142 + + CERR_90FeatureOnlyLayoutFile = 0x405C, + CERR_90FeatureOnlyKeyboardVersion = 0x405D, + CERR_KeyboardVersionFormatInvalid = 0x405E, + CERR_ContextExHasInvalidOffset = 0x405F, + CERR_90FeatureOnlyEmbedCSS = 0x4060, + CERR_90FeatureOnlyTargets = 0x4061, + CERR_ContextAndIndexInvalidInMatchNomatch = 0x4062, + CERR_140FeatureOnlyContextAndNotAnyWeb = 0x4063, + + CERR_ExpansionMustFollowCharacterOrVKey = 0x4064, + CERR_VKeyExpansionMustBeFollowedByVKey = 0x4065, + CERR_CharacterExpansionMustBeFollowedByCharacter = 0x4066, + CERR_VKeyExpansionMustUseConsistentShift = 0x4067, + CERR_ExpansionMustBePositive = 0x4068, + + CERR_CasedKeysMustContainOnlyVirtualKeys = 0x4069, + CERR_CasedKeysMustNotIncludeShiftStates = 0x406A, + CERR_CasedKeysNotSupportedWithMnemonicLayout = 0x406B, + + CERR_CannotUseReadWriteGroupFromReadonlyGroup = 0x406C, + CERR_StatementNotPermittedInReadonlyGroup = 0x406D, + CERR_OutputInReadonlyGroup = 0x406E, + CERR_NewContextGroupMustBeReadonly = 0x406F, + CERR_PostKeystrokeGroupMustBeReadonly = 0x4070, + + CERR_DuplicateGroup = 0x4071, + CERR_DuplicateStore = 0x4072, + + CWARN_TooManyWarnings = 0x2080, + CWARN_OldVersion = 0x2081, + CWARN_BitmapNotUsed = 0x2082, + CWARN_CustomLanguagesNotSupported = 0x2083, + CWARN_KeyBadLength = 0x2084, + CWARN_IndexStoreShort = 0x2085, + CWARN_UnicodeInANSIGroup = 0x2086, + CWARN_ANSIInUnicodeGroup = 0x2087, + CWARN_UnicodeSurrogateUsed = 0x2088, + CWARN_ReservedCharacter = 0x2089, + CWARN_Info = 0x208A, + CWARN_VirtualKeyWithMnemonicLayout = 0x208B, + CWARN_VirtualCharKeyWithPositionalLayout = 0x208C, + CWARN_StoreAlreadyUsedAsOptionOrCall = 0x208D, + CWARN_StoreAlreadyUsedAsStoreOrCall = 0x208E, + CWARN_StoreAlreadyUsedAsStoreOrOption = 0x208F, + + CWARN_PunctuationInEthnologueCode = 0x2090, + + CWARN_TouchLayoutMissingLayer = 0x2091, + CWARN_TouchLayoutCustomKeyNotDefined = 0x2092, + CWARN_TouchLayoutMissingRequiredKeys = 0x2093, + CWARN_HelpFileMissing = 0x2094, + CWARN_EmbedJsFileMissing = 0x2095, + CWARN_TouchLayoutFileMissing = 0x2096, + CWARN_VisualKeyboardFileMissing = 0x2097, + CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb = 0x2098, // I4118 + CWARN_TouchLayoutUnidentifiedKey = 0x2099, // I4142 + CHINT_UnreachableKeyCode = 0x109A, // I4141 + + CWARN_CouldNotCopyJsonFile = 0x209B, // I4688 + CWARN_PlatformNotInTargets = 0x209C, + + CWARN_HeaderStatementIsDeprecated = 0x209D, + CWARN_UseNotLastStatementInRule = 0x209E, + + CWARN_TouchLayoutFontShouldBeSameForAllPlatforms = 0x209F, // I4872 + CWARN_InvalidJSONMetadataFile = 0x20A0, // I4872 + CWARN_JSONMetadataOSKFontShouldMatchTouchFont = 0x20A1, // I4872 + + CWARN_DontMixChiralAndNonChiralModifiers = 0x20A3, + CWARN_MixingLeftAndRightModifiers = 0x20A4, + + CWARN_LanguageHeadersDeprecatedInKeyman10 = 0x20A5, + + CHINT_NonUnicodeFile = 0x10A6, + + CWARN_TooManyErrorsOrWarnings = 0x20A7, + + CWARN_HotkeyHasInvalidModifier = 0x20A8, + + CWARN_TouchLayoutSpecialLabelOnNormalKey = 0x20A9, + + CWARN_OptionStoreNameInvalid = 0x20AA, + + CWARN_NulNotFirstStatementInContext = 0x20AB, + CWARN_IfShouldBeAtStartOfContext = 0x20AC, + + CWARN_KeyShouldIncludeNCaps = 0x20AD, + + CHINT_UnreachableRule = 0x10AE, + CHINT_FilenameHasDifferingCase = 0x10AF, + CWARN_MissingFile = 0x20B0; diff --git a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts index 2d4b061d56..260a55d522 100644 --- a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts +++ b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts @@ -1,4 +1,8 @@ -import { GROUP, KEY, KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx"; +import { GROUP, KEY, KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx.js"; +import { nl, FTabStop, setupGlobals, IsKeyboardVersion10OrLater } from "./compiler-globals.js"; +import CompilerOptions from "./compiler-options.js"; +import { JavaScript_Name, JavaScript_Rules, JavaScript_Shift, JavaScript_Store } from './javascript-strings.js'; +import { CERR_InvalidBegin, CWARN_DontMixChiralAndNonChiralModifiers, ReportError } from "./messages.js"; function requote(s: string): string { return "'" + s.replaceAll(/(['\\])/, "\\$1") + "'"; @@ -27,8 +31,11 @@ function RequotedString(s: string, RequoteSingleQuotes: boolean = false): string } export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boolean = false): string { - let nl = FDebug ? '\n' : ''; - let FTabStop = FDebug ? ' ' : ''; + let opts: CompilerOptions = { + addCompilerVersion: false, + debug: FDebug + }; + setupGlobals(opts, FDebug?' ':'', FDebug?'\n':'', source.keyboard); // let fgp: GROUP; @@ -255,7 +262,7 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo let fsp = source.keyboard.stores[i]; // I3438 - Save all system stores to the keyboard, for now // I3684 - if (!fsp.fIsDebug) { // and not (fsp.dwSystemID in [TSS_BITMAP, TSS_NAME, TSS_VERSION, TSS_CUSTOMKEYMANEDITION, TSS_CUSTOMKEYMANEDITIONNAME, TSS_KEYMANCOPYRIGHT]) then + if (!isDebugStore(fsp)) { // and not (fsp.dwSystemID in [TSS_BITMAP, TSS_NAME, TSS_VERSION, TSS_CUSTOMKEYMANEDITION, TSS_CUSTOMKEYMANEDITIONNAME, TSS_KEYMANCOPYRIGHT]) then if (fsp.dwSystemID == KMXFile.TSS_COMPARISON) { result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(fsp.line, fsp.dpString)};${nl}`; } @@ -264,17 +271,17 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo } //else if fsp.dwSystemID = TSS_VKDICTIONARY then // I3438, required for vkdictionary // Result := Result + Format('%sthis.s%s=%s;%s', [FTabStop, JavaScript_Name(i, fsp.szName), JavaScript_Store(fsp.line, fsp.dpString), nl]) - else if (fsp.fIsOption && !fsp.fIsReserved) { - result += `${FTabStop}this.s${JavaScript_Name(i,fsp.szName)}=KeymanWeb.KLOAD(this.KI,"${JavaScript_Name(i,fsp.szName,true)}",`+ + else if (isOptionStore(fsp) && !isReservedStore(fsp)) { + result += `${FTabStop}this.s${JavaScript_Name(i,fsp.dpName)}=KeymanWeb.KLOAD(this.KI,"${JavaScript_Name(i,fsp.dpName,true)}",`+ `${JavaScript_Store(fsp.line, fsp.dpString)});${nl}`; if (FOptionStores != '') { FOptionStores += ','; } - FOptionStores += `'s${JavaScript_Name(i,fsp.szName)}`; + FOptionStores += `'s${JavaScript_Name(i, fsp.dpName)}`; } else if (fsp.dwSystemID == KMXFile.TSS_NONE /* aka not fsp.fIsReserved */) { - result += `${FTabStop}this.s${JavaScript_Name(i, fsp.szName)}=${JavaScript_Store(fsp.line, fsp.dpString)};${nl}`; // I3681 + result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(fsp.line, fsp.dpString)};${nl}`; // I3681 } } } @@ -284,7 +291,7 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo // Write the groups out // I853 - begin unicode missing causes crash - if (fk.StartGroup[KMXFile.BEGIN_UNICODE] == 0xFFFFFFFF) { + if (source.keyboard.startGroup.unicode == 0xFFFFFFFF) { ReportError(0, CERR_InvalidBegin, 'A "begin unicode" statement is required to compile a KeymanWeb keyboard'); return null; } @@ -292,11 +299,11 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo result += WriteBeginStatement('gs', source.keyboard.startGroup.unicode); let rec = ExpandSentinel(sBegin_NewContext); - if(rec.Code == CODE_USE) { + if(rec.Code == KMXFile.CODE_USE) { result += WriteBeginStatement('gn', rec.Use.GroupIndex); } rec = ExpandSentinel(sBegin_PostKeystroke); - if(rec.Code == CODE_USE) { + if(rec.Code == KMXFile.CODE_USE) { result += WriteBeginStatement('gpk', rec.Use.GroupIndex); } @@ -346,7 +353,7 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo for (let j = 0; j < fgp.keys.length; j++) { // I1964 let fkp = fgp.keys[j]; if (!RuleIsExcludedByPlatform(fkp)) { - result += FTabstop+FTabstop; // I3681 + result += FTabStop+FTabStop; // I3681 if (HasRules) { result += 'else '; } @@ -380,40 +387,32 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo } } - if Assigned(fgp.dpMatch) then - Result := Result + Format( - '%sif(m==1) {%s'+ - '%s%s%s'+ - '%s}%s', - [FTabstop+FTabstop, nl, - FTabstop+Ftabstop, JavaScript_OutputString(FTabStop + FTabStop + FTabStop, nil, fgp.dpMatch, fgp), nl, - FTabstop+FTabstop, nl]); // I3681 - if Assigned(fgp.dpNoMatch) then - if fgp.fUsingKeys then // I1382 - fixup m=1 to m=g() - Result := Result + Format( - '%sif(!m&&k.KIK(e)) {%s'+ - '%sr=1;%s%s'+ - '%s}%s', - [FTabstop+FTabstop, nl, - FTabstop+FTabstop+FTabstop, JavaScript_OutputString(FTabStop + FTabStop + FTabStop, nil, fgp.dpNoMatch, fgp), nl, - FTabstop+FTabstop, nl]) // I1959. part 2, I2224 // I3681 - else - Result := Result + Format( - '%sif(!m) {%s'+ - '%s%s%s'+ - '%s}%s', - [FTabstop+FTabstop, nl, - FTabstop+FTabstop, JavaScript_OutputString(FTabStop + FTabStop + FTabStop, nil, fgp.dpNoMatch, fgp), nl, - FTabstop+FTabstop, nl]); // I1959 // I3681 + if(fgp.dpMatch) { + result += + `${FTabStop+FTabStop}if(m==1) {${nl}`+ + `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(FTabStop + FTabStop + FTabStop, null, fgp.dpMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop}}${nl}`; + } + if(fgp.dpNoMatch) { + if(fgp.fUsingKeys) { // I1382 - fixup m=1 to m=g() + result += + `${FTabStop+FTabStop}if(!m&&k.KIK(e)) {${nl}`+ + `${FTabStop+FTabStop+FTabStop}r=1;${JavaScript_OutputString(FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop}}${nl}`; // I1959. part 2, I2224 // I3681 + } + else { + result += + `${FTabStop+FTabStop}if(!m) {${nl}`+ + `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop}}${nl}`; + } - Result := Result + Format('%sreturn r;%s'+ - '%s};%s', - [FTabstop+FTabstop, nl, - FTabstop, nl]); // I1959 // I3681 - Inc(fgp); - end; - - for n := 0 to FCallFunctions.Count - 1 do + result += + `${FTabStop+FTabStop}return r;${nl}`+ + `${FTabStop+FTabStop}};${nl}`; + } +/* TODO + for(let n = 0 to FCallFunctions.Count - 1 do begin s := ExtractFilePath(FInFile) + FCallFunctions[n] + '.call_js'; if FileExists(s) then @@ -427,9 +426,9 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo else Result := Result + Format('%sthis.c%d=function(t,e){alert("call(%s) not defined");};%s', [FTabstop, n, FCallFunctions[n], nl]); // I3681 end; - - Result := Result + sEmbedJS + '}' + nl; // I3681 -end; +*/ + result += sEmbedJS + '}' + nl; // I3681 + return result; } /// From 13e80676001583a80717d85f5b8a128ba8908534 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 6 Jan 2023 07:05:09 +0700 Subject: [PATCH 04/21] feat: kmc-kmw more conversions --- .../kmc-kmw/src/compiler/compiler-globals.ts | 2 +- .../src/compiler/javascript-strings.ts | 615 ++++++++++++++++-- .../src/compiler/write-compiled-keyboard.ts | 93 ++- developer/src/kmc-kmw/src/util/util.ts | 244 +++++++ 4 files changed, 884 insertions(+), 70 deletions(-) diff --git a/developer/src/kmc-kmw/src/compiler/compiler-globals.ts b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts index f769c768ba..067fea1d51 100644 --- a/developer/src/kmc-kmw/src/compiler/compiler-globals.ts +++ b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts @@ -1,4 +1,4 @@ -import { KEYBOARD, KMXFile } from "@keymanapp/common-types/src/kmx/kmx"; +import { KEYBOARD, KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; import CompilerOptions from "./compiler-options.js"; export let FTabStop: string; diff --git a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts index 8b95d484f0..eaf31a08a3 100644 --- a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts +++ b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts @@ -1,7 +1,9 @@ -import { GROUP, KEY, KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; +import { TSentinelRecord, GetSuppChar, ExpandSentinel, incxstr, xstrlen, xstrlen_printing } from "src/util/util.js"; +import { GROUP, KEY, KEYBOARD, KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; import { FMnemonic, FTabStop, IsKeyboardVersion10OrLater, nl, options } from "./compiler-globals.js"; -import { CERR_VirtualCharacterKeysNotSupportedInKeymanWeb, CERR_VirtualKeysNotValidForMnemonicLayouts, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, CWARN_OptionStoreNameInvalid, ReportError } from "./messages.js"; +import { CERR_InvalidBegin, CERR_NotSupportedInKeymanWebContext, CERR_VirtualCharacterKeysNotSupportedInKeymanWeb, CERR_VirtualKeysNotValidForMnemonicLayouts, CHINT_UnreachableKeyCode, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, CWARN_OptionStoreNameInvalid, ReportError } from "./messages.js"; +import { FFix183_LadderLength, RuleIsExcludedByPlatform } from "./write-compiled-keyboard.js"; //const SValidIdentifierCharSet = '123'; @@ -36,14 +38,13 @@ export function JavaScript_Name(i: number, pwszName: string, KeepNameForPersiste // For named option stores, we are only supporting the valid identifier // character set, which is a breaking change in 14.0. ReportError(0, CWARN_OptionStoreNameInvalid, - Format('The option store %s should be named with characters in the range A-Z, a-z, 0-9 and _ only.', - [pwszName])); + `The option store ${pwszName} should be named with characters in the range A-Z, a-z, 0-9 and _ only.`); } return result; } } -export function JavaScript_Store(line: number, pwsz: string): string { +export function JavaScript_Store(fk: KEYBOARD, line: number, pwsz: string): string { let ch: number, rec: TSentinelRecord, result: string; const wcsentinel: string = '\uFFFF'; let n = pwsz.indexOf(wcsentinel); @@ -55,13 +56,14 @@ export function JavaScript_Store(line: number, pwsz: string): string { if(pwsz.charCodeAt(0) == KMXFile.UC_SENTINEL) { result += '.'; // UC_SENTINEL values are not supported in stores for KMW < 10.0. } else { - ch = GetSuppChar(pwsz); - if(ch == '"' || ch == '\\') { + ch = GetSuppChar(pwsz, 0); + if(ch == '"'.charCodeAt(0) || ch == '\\'.charCodeAt(0)) { result += '\\'; } result += JavaScript_String(ch); // I2242 } + // TODO: problems with supp chars pwsz = pwsz.substring(1); } result += '"'; @@ -72,10 +74,10 @@ export function JavaScript_Store(line: number, pwsz: string): string { if(result != '[') { result += ','; } - rec = ExpandSentinel(pwsz); + rec = ExpandSentinel(fk, pwsz, 0); if(rec.IsSentinel) { if(rec.Code == KMXFile.CODE_DEADKEY) { - result += `{t:'d',d:${rec.Deadkey.DeadKey}}`; + result += `{t:'d',d:${rec.DeadKey.DeadKey}}`; } else if(rec.Code == KMXFile.CODE_BEEP) { result += `{t:'b'}`; @@ -92,7 +94,7 @@ export function JavaScript_Store(line: number, pwsz: string): string { // end; } else { - ch = GetSuppChar(pwsz); + ch = GetSuppChar(pwsz, 0); result += '"'; // TODO: Refactor the section below into JavaScript_String, as it's // quite common in our code base. @@ -264,49 +266,46 @@ export function JavaScript_ShiftAsString(fkp: KEY, FMnemonic: boolean): string { -function TCompileKeymanWeb.JavaScript_Key(fkp: PFILE_KEY; FMnemonic: Boolean): Integer; -var - n: Integer; - i: Integer; -begin - if not FMnemonic then - begin - if (fkp.ShiftFlags and KMX_ISVIRTUALKEY) = KMX_ISVIRTUALKEY then - begin - Result := Ord(fkp.Key); - end - else - begin +function JavaScript_Key(fkp: KEY, FMnemonic: boolean): number { + let Result: number; + if(!FMnemonic) { + if(fkp.ShiftFlags & KMXFile.ISVIRTUALKEY) { + Result = fkp.Key; + } + else { // Convert the character to a virtual key - n := Pos(fkp.Key, USEnglishShift); - if n = 0 then n := Pos(fkp.Key, USEnglishUnshift); - if n = 0 - then Result := 0 - else Result := Ord(USEnglishValues[n]); - end; - end - else - begin - Result := Ord(fkp.Key); - end; + let n = USEnglishShift.indexOf(String.fromCharCode(fkp.Key)); + if(n < 0) { + n = USEnglishUnshift.indexOf(String.fromCharCode(fkp.Key)); + } + if(n < 0) { + Result = 0; + } + else { + Result = USEnglishValues.charCodeAt(n); + } + } + } + else { + Result = fkp.Key; + } // Check that key is not unreachable (e.g. K_SHIFT, touch-specific special keys 50,000+) - for i := 0 to High(UnreachableKeyCodes) do // I4141 - if Result = UnreachableKeyCodes[i] then - Result := 0; + if(UnreachableKeyCodes.indexOf(Result) >= 0) { + Result = 0; + } - if (Result = 0) or (Result >= Ord(Low(TKeymanWebTouchStandardKey))) then // I4141 - begin - if not FUnreachableKeys.Contains(fkp) then - begin + if (Result == 0 || Result >= Ord(Low(TKeymanWebTouchStandardKey))) { // I4141 + if(!FUnreachableKeys.includes(fkp)) { ReportError(fkp.Line, CHINT_UnreachableKeyCode, 'The rule will never be matched for key '+ FormatKeyForErrorMessage(fkp,FMnemonic)+' because its key code is never fired.'); - FUnreachableKeys.Add(fkp); - end; - end; -end; + FUnreachableKeys.push(fkp); + } + } + return Result; +} /// /// Returns a Javascript representation of a key value, either as a constant (debug mode) @@ -317,7 +316,7 @@ end; /// /// @return string representation of the key value, e.g. 'keyCodes.K_A /* 0x41 */' or '65' /// -function JavaScript_KeyAsString(fkp: KEY, FMnemonic: boolean): string { +export function JavaScript_KeyAsString(fkp: KEY, FMnemonic: boolean): string { if(options.debug) { return ' '+FormatKeyAsString(JavaScript_Key(fkp, FMnemonic)); } else { @@ -325,3 +324,527 @@ function JavaScript_KeyAsString(fkp: KEY, FMnemonic: boolean): string { } } +export function JavaScript_ContextMatch(fk: KEYBOARD, fkp: KEY, context: string): string { + if(IsKeyboardVersion10OrLater()) { + return JavaScript_FullContextValue(fk, fkp, context); + } + else { + return JavaScript_CompositeContextValue(fk, fkp, context); + } +} + +// Used when targeting versions prior to 10.0, before the introduction of FullContextMatch/KFCM. +function JavaScript_CompositeContextValue(fk: KEYBOARD, fkp: KEY, pwsz: string): string { + // Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions +// var + // StartQuotes, Len, Cur: Integer; + // InQuotes: Boolean; + // rec: TSentinelRecord; + + let Result = ''; + + let InQuotes = false; + let Len = JavaScript_ContextLength(pwsz); + let StartQuotes = -1; + let x = 0, Cur = 0; + + while(x < pwsz.length) { + let rec = ExpandSentinel(fk, pwsz, x); + if(rec.IsSentinel) { + if(InQuotes) { + Result += `",${Cur-StartQuotes})`; + InQuotes = false; + } + if(Result != '') { + Result += '&&'; + } + + switch(rec.Code) { + case KMXFile.CODE_ANY: + CheckStoreForInvalidFunctions(fkp, rec.Any.Store); // I1520 + Result += `k.KA(${Cur},k.KC(${Len-Cur},1,t),this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)})`; + break; + case KMXFile.CODE_DEADKEY: + Result += `k.KDM(${Len-Cur},t,${rec.DeadKey.DeadKey})`; + Cur--; // don't increment on deadkeys -- correlates with AdjustIndex function // I3910 + break; + case KMXFile.CODE_NUL: // I2243 + Result += `k.KN(${Len-Cur},t)`; + Cur--; // don't increment on nul -- correlates with AdjustIndex function // I3910 + break; + case KMXFile.CODE_IFOPT: // I3429 + Result += `this.s${JavaScript_Name(rec.IfOpt.StoreIndex1, rec.IfOpt.Store1.dpName)}`+ + `${rec.IfOpt.IsNot == 0 ? '!==':'==='}`+ + `this.s${JavaScript_Name(rec.IfOpt.StoreIndex2,rec.IfOpt.Store2.dpName)}`; // I3429 // I3659 // I3681 + Cur--; // don't increment on ifopt -- correlates with AdjustIndex function // I3910 + break; + case KMXFile.CODE_IFSYSTEMSTORE: // I3430 + Result += `${rec.IfSystemStore.IsNot == 0 ? '!' : ''}`+ + `k.KIFS(${rec.IfSystemStore.dwSystemID},`+ + `this.s${JavaScript_Name(rec.IfSystemStore.StoreIndex,rec.IfSystemStore.Store.dpName)},t)`; + Cur--; // don't increment on ifsystemstore -- correlates with AdjustIndex function // I3910 + break; + case KMXFile.CODE_CONTEXTEX: // I3980 + Result += `k.KCCM(${Len-Cur},${Len-rec.ContextEx.Index+1},t)`; + break; + case KMXFile.CODE_NOTANY: // I3981 + CheckStoreForInvalidFunctions(fkp, rec.Any.Store); // I1520 + Result += `k.KC(${Len-Cur},1,t)!=""&&!k.KA(${Cur},k.KC(${Len-Cur},1,t),`+ + `this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)})`; + break; + default: + ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, + `Statement ${GetCodeName(rec.Code)} is not currently supported in context`); // I1971 // I4061 + Result += '/*.*/ 0 '; + } + } + else { + if(!InQuotes) { + if(Result != '') { + Result += '&&'; + } + Result += `k.KCM(${Len-Cur},t,"`; + StartQuotes = Cur; + InQuotes = true; + } + if(rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0)) { + Result += '\\'; + } + Result += Javascript_String(rec.ChrVal); // I2242 + } + + Cur++; + x = incxstr(pwsz, x); + } + + if(InQuotes) { + Result += `",${Cur - StartQuotes})`; + } + return Result; +} + +// Used when targeting versions >= 10.0, after the introduction of FullContextMatch/KFCM. +function JavaScript_FullContextValue(fk: KEYBOARD, fkp: KEY, pwsz: string): string { +/*var + Len: Integer; + rec: TSentinelRecord; + FullContext, Suffix: string; +begin*/ + let Result = ''; + let FullContext = ''; + let Suffix = ''; + let Len = xstrlen(pwsz); + let x = 0; + + while(x < pwsz.length) { + if(FullContext != '') { + FullContext += ','; + } + + let rec = ExpandSentinel(fk, pwsz, x); + if(rec.IsSentinel) { + switch(rec.Code) { + case KMXFile.CODE_ANY: + CheckStoreForInvalidFunctions(fkp, rec.Any.Store); // I1520 + FullContext += `{t:'a',a:this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)}}`; + break; + case KMXFile.CODE_DEADKEY: + FullContext += `{t:'d',d:${rec.DeadKey.DeadKey}}`; + break; + case KMXFile.CODE_NUL: // I2243 + FullContext += `{t:'n'}`; + break; + case KMXFile.CODE_IFOPT: // I3429 + Len--; + if(Suffix != '') { + Suffix += '&&'; + } + if(FullContext == ',') { + FullContext = ''; + } + Suffix += `this.s${JavaScript_Name(rec.IfOpt.StoreIndex1, rec.IfOpt.Store1.dpName)}`+ + `${rec.IfOpt.IsNot == 0 ? '!==' : '==='}this.s${JavaScript_Name(rec.IfOpt.StoreIndex2,rec.IfOpt.Store2.dpName)}`; // I3429 // I3659 // I3681 + break; + case KMXFile.CODE_IFSYSTEMSTORE: // I3430 + Len--; + if(Suffix != '') { + Suffix += '&&'; + } + if(FullContext == ',') { + FullContext = ''; + } + Suffix += `${rec.IfSystemStore.IsNot == 0 ? '!' : ''}k.KIFS(${rec.IfSystemStore.dwSystemID},`+ + `this.s${JavaScript_Name(rec.IfSystemStore.StoreIndex,rec.IfSystemStore.Store.dpName)},t)`; // I3430 // I3659 // I3681 + break; + case KMXFile.CODE_NOTANY: // I3981 + CheckStoreForInvalidFunctions(fkp, rec.Any.Store); // I1520 + FullContext += `{t:'a',a:this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)},n:1}`; + break; + case KMXFile.CODE_CONTEXTEX: + FullContext += `{t:'c',c:${rec.ContextEx.Index}}`; // I4611 + break; + case KMXFile.CODE_INDEX: + FullContext += `{t:'i',i:this.s${JavaScript_Name(rec.Index.StoreIndex, rec.Index.Store.szName)},`+ + `o:${rec.Index.Index}}`; // I4611 + break; + default: + ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, `Statement ${GetCodeName(rec.Code)} is not currently supported in context`; // I1971 // I4061 + Result += '/*.*/ 0 '; + } + } + else + { // Simple context character. + FullContext += `'`; + if(rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0) || rec.ChrVal == '\''.charCodeAt(0)) { + FullContext += '\\'; + } + FullContext += Javascript_String(rec.ChrVal) + `'`; // I2242 + } + + x = incxstr(pwsz, x); + } + + if(FullContext != '') { + Result = `k.KFCM(${Len},t,[${FullContext}])`; + } + + if (Result != '' && Suffix != '') { + Result += '&&' + Suffix; + } + else if(Suffix != '') { + Result = Suffix; + } + return Result; +} + +export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KEY, pwszOutput: string, fgp: GROUP): string { + let InQuotes = false; + let len = 0; + const nlt = nl + FTabStops; // I3681 + +/*var + i, n, len: Integer; + InQuotes: Boolean; + rec: TSentinelRecord; + pwszcontext,pwsz: PWideChar; + Index: Integer; // I3910 + nlt: string;*/ + + const AdjustIndex = function(pwszContext: string, Index: number): number { // I3910 + let Result = Index; + let x = 0; + for(let I = 1; I < Index; I++) { + let recContext = ExpandSentinel(fk, pwszContext, x); + + if(IsKeyboardVersion10OrLater()) { + if(recContext.IsSentinel && [KMXFile.CODE_NUL, KMXFile.CODE_IFOPT, KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) { + Result--; + } + } + else { + if(recContext.IsSentinel && [KMXFile.CODE_DEADKEY, KMXFile.CODE_NUL,KMXFile. KMXFile.CODE_IFOPT, KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) { + Result--; + } + } + x = incxstr(pwszContext, x); + } + return Result; + } + + const ContextChar = function(ContextIndex: number, pwszContext: string, xContext: number): string { // I4611 + let Index: number; + let Result = ''; + let recContext = ExpandSentinel(fk, pwszContext, xContext); + if(recContext.IsSentinel) { + if(InQuotes) { // I4611 + Result += '");'; + InQuotes =false; + } + + switch(recContext.Code) { + case KMXFile.CODE_ANY: + Index = AdjustIndex(fkp.dpContext, ContextIndex); // I3910 // I4611 + Result += nlt + `k.KIO(${len},this.s${JavaScript_Name(recContext.Any.StoreIndex, recContext.Any.Store.dpName)},${Index},t);`; // I4611 + break; + case KMXFile.CODE_DEADKEY: + Result += nlt + `k.KDO(${len},t,${recContext.DeadKey.DeadKey});`; // I4611 + break; + case KMXFile.CODE_NOTANY: + // #917: Minimum version required is 14.0: the KCXO function was only added for 14.0 + // Note that this is checked in compiler.cpp as well, so this error can probably never occur + if(!IsKeyboardVersion14OrLater()) { + ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, `Statement notany in context() match requires version 14.0+ of KeymanWeb`); // I1971 // I4061 + } + Result += nlt + `k.KCXO(${len},t,${AdjustIndex(fkp.dpContext, xstrlen(fkp.dpContext))},${AdjustIndex(fkp.dpContext, ContextIndex)});`; + break; + case KMXFile.CODE_IFOPT: + case KMXFile.CODE_IFSYSTEMSTORE: + case KMXFile.CODE_NUL: + // These have no output for a context emit + break; + default: + ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, `Statement ${GetCodeName(recContext.Code)} is not currently supported in context() match`); // I1971 // I4061 + Result += nlt + '/*.*/ '; // I4611 + } + } + else { + if(!InQuotes) { + Result += nlt + `k.KO(${len},t,"`; // I4611 + InQuotes = true; + } + + if(recContext.ChrVal == '"'.charCodeAt(0) || recContext.ChrVal == '\\'.charCodeAt(0)) { + Result += '\\'; + } + Result += JavaScript_String(recContext.ChrVal); // I2242 + } + return Result; + } + + let Result = ''; + InQuotes = false; + + let pwsz = pwszOutput; + + if(fkp != null) { + if(IsKeyboardVersion10OrLater()) { + // KMW >= 10.0 use the full, sentinel-based length for context deletions. + len = xstrlen(fkp.dpContext); + n = len; + + let x = 0; + for(let i = 0; i < n; i++) { + let rec = ExpandSentinel(fk, fkp.dpContext, x); + if(rec.IsSentinel && [KMXFile.CODE_NUL, KMXFile.CODE_IFOPT, KMXFile.CODE_IFSYSTEMSTORE].includes(rec.Code)) { + len--; + } + x = incxstr(fkp.dpContext, x); + } + } + else { + // KMW < 10.0 exclude all sentinel-based characters, including deadkeys, from direct context deletion. + // Deadkeys have alternative special handling. + len = xstrlen_printing(fkp.dpContext); + } + } + else { + len = -1; + } + + let x = 0; + if(IsKeyboardVersion10OrLater() && pwsz.length > 0) { + if(fgp.fReadOnly) { + Result += nlt+`k.KDC(${len},t);`; // I3681 + } + len = -1; + } + + while(x < pwsz.length) { + let rec = ExpandSentinel(fk, pwsz, x); + if(rec.IsSentinel) { + if(InQuotes) { + if(!fgp.fReadOnly) { + Result += '");'; + } + InQuotes = false; + } + + switch(rec.Code) { + case KMXFile.CODE_CONTEXT: + if (x > 0 || len == -1) { + let xContext = 0; + n = 1; + while(xContext < fkp.dpContext.length) { // I4611 + if(!fgp.fReadOnly) { + Result += ContextChar(n, fkp.dpContext, xContext); + } + n++; + xContext = incxstr(fkp.dpContext, xContext); + } + //Result := Result + Format('k.KO(%d,t,k.KC(%d,%d,t));', [len, xstrlen_printing(fkp.dpContext), xstrlen_printing(fkp.dpContext)]); + } + // else, we don't need to output anything - just don't delete the context + len = -1; + break; + case KMXFile.CODE_CONTEXTEX: + let xContext = 0; + for(let i = 0; i < rec.ContextEx.Index; i++) { + xContext = incxstr(fkp.dpContext, xContext); + } + + if(!fgp.fReadOnly) { + Result += ContextChar(rec.ContextEx.Index, fkp.dpContext, xContext); // I4611 + } + len = -1; + break; + case KMXFile.CODE_BEEP: + if(!fgp.fReadOnly) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + Result += nlt+'k.KB(t);'; // I3681 + } + len = -1; + break; + case KMXFile.CODE_NUL: + if(!fgp.fReadOnly) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + len = -1; + break; + case KMXFile.CODE_INDEX: + CheckStoreForInvalidFunctions(fkp, rec.Index.Store); // I1520 + + // This code was wrong. We need to ignore CODE_NUL, CODE_DEADKEY in LHS context index counter. + // This is why the compiler goes wrong -- and why the previous fix was inconsistent. + // The I783 test did not test either of these cases. It seems some of the keyboards were + // compiled in-between the original fix and I783 re-fix, and then happened to work due to + // their simplicity. + + let Index = AdjustIndex(fkp.dpContext, rec.Index.Index); // I3910 + + if(!fgp.fReadOnly) { + Result += nlt+`k.KIO(${len},this.s${JavaScript_Name(rec.Index.StoreIndex, rec.Index.Store.dpName)},${Index},t);`; + // I783 - was: rec.Index.Index [2007-06-04] + // I783 again. Returned to rec.Index.Index. Was previously: [2008-08-15] + // xstrlen(fkp.dpContext) + 1 - rec.Index.Index]); + // this was wrong. Can't find any reason why this change was made + // which suggests it was in response to another bug and poorly traced (bad Marc) + // and not properly tested (bad, bad Marc). Anyway, now tested with test_i783 + } + len = -1; + break; + case KMXFile.CODE_DEADKEY: + if(!fgp.fReadOnly) { + Result += nlt+`k.KDO(${len},t,${rec.DeadKey.DeadKey});`; // I3681 + } + len = -1; + break; + case KMXFile.CODE_USE: + if(!fgp.fReadOnly) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + Result += nlt+`r=this.g${JavaScript_Name(rec.Use.GroupIndex, rec.Use.Group.dpName)}(t,e);`; // I1959 // I3681 + Result += nlt+'m=2;'; // #5440 - match desktop behavior + len = -1; + break; + case KMXFile.CODE_CALL: + if(!fgp.fReadOnly) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + n = FCallFunctions.IndexOf(CallFunctionName(rec.Call.Store.dpString)); + if(n == -1) { + n = FCallFunctions.Add(CallFunctionName(rec.Call.Store.dpString)); + } + Result += nlt+`r=this.c${n}(t,e);`; // I1959 // I3681 + Result += nlt+'m=2;'; // #5440 - match desktop behavior + len = -1; + break; + case KMXFile.CODE_SETOPT: // I3429 + if(!fgp.fReadOnly) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + Result += nlt+`this.s${JavaScript_Name(rec.SetOpt.StoreIndex1,rec.SetOpt.Store1.dpName)}=`+ + `this.s${JavaScript_Name(rec.SetOpt.StoreIndex2,rec.SetOpt.Store2.dpName)};`; + len = -1; + break; + case KMXFile.CODE_RESETOPT: // I3429 + if(!fgp.fReadOnly) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + + Result += nlt+`this.s${JavaScript_Name(rec.ResetOpt.StoreIndex,rec.ResetOpt.Store.dpName)}=`+ + `k.KLOAD(this.KI,"${JavaScript_Name(rec.ResetOpt.StoreIndex,rec.ResetOpt.Store.dpName,true)}",`+ + `${JavaScript_Store(fkp.Line, rec.ResetOpt.Store.dpString)});`; // I3429 // I3681 // I3659 + len = -1; + break; + case KMXFile.CODE_SAVEOPT: // I3429 + if(!fgp.fReadOnly) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + + Result += nlt+`k.KSAVE("${JavaScript_Name(rec.SaveOpt.StoreIndex,rec.SaveOpt.Store.dpName,true)}",`+ + `this.s${JavaScript_Name(rec.SaveOpt.StoreIndex,rec.SaveOpt.Store.dpName)});`; // I3690 // I3429 // I3659 // I3681 + len = -1; + break; + case KMXFile.CODE_SETSYSTEMSTORE: // I3437 + if(!fgp.fReadOnly) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + + Result += nlt+`k.KSETS(${rec.SetSystemStore.dwSystemID},`+ + `this.s${JavaScript_Name(rec.SetSystemStore.StoreIndex, rec.SetSystemStore.Store.dpName)},t);`; // I3681 + len = -1; + break; + default: + ReportError(fkp ? fkp.Line : 0, CERR_NotSupportedInKeymanWebOutput, `Statement ${GetCodeName(rec.Code)} is not currently supported in output`); // I1971 // I4061 + Result += ''; + } + } + else { + if(!InQuotes) { + if(!fgp.fReadOnly) { + if(len > 0) { + Result += nlt+`k.KO(${len},t,"");`; // I3681 + } + } + InQuotes = true; len = -1; + } + + if(!fgp.fReadOnly) { + if(rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0)) { + Result += '\\'; + } + Result += JavaScript_String(rec.ChrVal); // I2242 + } + } + + x = incxstr(pwsz, x); + } + + if(InQuotes) { + if(!fgp.fReadOnly) { + Result += '");'; + } + } + return Result; +} + +function zeroPadHex(n: number, len: number): string { + let result = n.toString(16); + if(result.length < len) { + return + } +} + +/** + * Converts a key value into a constant + * + * @param key A virtual key code + * + * @return string of JavaScript code, e.g. 'keyCodes.K_A /* 0x41 * /' + */ +function FormatKeyAsString(key: number): string { + if(IsKeyboardVersion10OrLater()) { + // Depends on flags defined in KeymanWeb 10.0 + if (key <= 255 && KMWVKeyNames[key] != '') { + Result = 'keyCodes.'+KMWVKeyNames[key]+ ' /* 0x' + zeroPadHex(key, 2) + ' */' + else Result := '0x' + IntToHex(key, 2); + end + else + Result := '0x' + IntToHex(key, 2); +end; diff --git a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts index 260a55d522..b065a1ea0f 100644 --- a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts +++ b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts @@ -1,9 +1,12 @@ +import { ExpandSentinel, incxstr, xstrlen } from "src/util/util.js"; import { GROUP, KEY, KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx.js"; -import { nl, FTabStop, setupGlobals, IsKeyboardVersion10OrLater } from "./compiler-globals.js"; +import { options, nl, FTabStop, setupGlobals, IsKeyboardVersion10OrLater } from "./compiler-globals.js"; import CompilerOptions from "./compiler-options.js"; -import { JavaScript_Name, JavaScript_Rules, JavaScript_Shift, JavaScript_Store } from './javascript-strings.js'; +import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaScript_OutputString, JavaScript_Rules, JavaScript_Shift, JavaScript_ShiftAsString, JavaScript_Store } from './javascript-strings.js'; import { CERR_InvalidBegin, CWARN_DontMixChiralAndNonChiralModifiers, ReportError } from "./messages.js"; +export let FFix183_LadderLength: number = 100; // TODO: option + function requote(s: string): string { return "'" + s.replaceAll(/(['\\])/, "\\$1") + "'"; } @@ -256,6 +259,19 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo result += `${FTabStop}this.KCSS="${RequotedString(sEmbedCSS)}";${nl}`; } + function isDebugStore(fsp: STORE) { + return fsp.dwSystemID == KMXFile.TSS_DEBUG_LINE; + } + + function isReservedStore(fsp: STORE) { + return fsp.dwSystemID != KMXFile.TSS_NONE; + } + + function isOptionStore(fsp: STORE) { + // TODO: how do we determine this, see CheckStoreUsage() + return false; + } + // Write the stores out FOptionStores = ''; for(let i = 0; i < source.keyboard.stores.length; i++) { @@ -296,15 +312,15 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo return null; } - result += WriteBeginStatement('gs', source.keyboard.startGroup.unicode); + result += WriteBeginStatement(source, 'gs', source.keyboard.startGroup.unicode); - let rec = ExpandSentinel(sBegin_NewContext); + let rec = ExpandSentinel(source.keyboard, sBegin_NewContext, 0); if(rec.Code == KMXFile.CODE_USE) { - result += WriteBeginStatement('gn', rec.Use.GroupIndex); + result += WriteBeginStatement(source, 'gn', rec.Use.GroupIndex); } - rec = ExpandSentinel(sBegin_PostKeystroke); + rec = ExpandSentinel(source.keyboard, sBegin_PostKeystroke, 0); if(rec.Code == KMXFile.CODE_USE) { - result += WriteBeginStatement('gpk', rec.Use.GroupIndex); + result += WriteBeginStatement(source, 'gpk', rec.Use.GroupIndex); } let fgp = source.keyboard.groups[source.keyboard.startGroup.unicode]; @@ -352,7 +368,7 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo else { for (let j = 0; j < fgp.keys.length; j++) { // I1964 let fkp = fgp.keys[j]; - if (!RuleIsExcludedByPlatform(fkp)) { + if (!RuleIsExcludedByPlatform(source, fkp)) { result += FTabStop+FTabStop; // I3681 if (HasRules) { result += 'else '; @@ -365,7 +381,7 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo if (xstrlen(fkp.dpContext) > 0) { result += fgp.fUsingKeys ? '&&' : 'if('; - result += JavaScript_ContextMatch(fkp, fkp.dpContext); + result += JavaScript_ContextMatch(source.keyboard, fkp, fkp.dpContext); } else if (!fgp.fUsingKeys) { result += 'if(1'; @@ -377,10 +393,10 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo `) {${linecomment}${nl}` + FTabStop+FTabStop+FTabStop; if (fgp.fUsingKeys) { // I1959 - result += 'r=m=1;' + JavaScript_OutputString(FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 + result += 'r=m=1;' + JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 } else { - result += 'm=1;' + JavaScript_OutputString(FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 + result += 'm=1;' + JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 } result += `${nl}${FTabStop}${FTabStop}}${nl}`; // I3681 } @@ -390,20 +406,20 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo if(fgp.dpMatch) { result += `${FTabStop+FTabStop}if(m==1) {${nl}`+ - `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(FTabStop + FTabStop + FTabStop, null, fgp.dpMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpMatch, fgp)}${nl}`+ `${FTabStop+FTabStop}}${nl}`; } if(fgp.dpNoMatch) { if(fgp.fUsingKeys) { // I1382 - fixup m=1 to m=g() result += `${FTabStop+FTabStop}if(!m&&k.KIK(e)) {${nl}`+ - `${FTabStop+FTabStop+FTabStop}r=1;${JavaScript_OutputString(FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop+FTabStop}r=1;${JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ `${FTabStop+FTabStop}}${nl}`; // I1959. part 2, I2224 // I3681 } else { result += `${FTabStop+FTabStop}if(!m) {${nl}`+ - `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ `${FTabStop+FTabStop}}${nl}`; } @@ -411,6 +427,8 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo `${FTabStop+FTabStop}return r;${nl}`+ `${FTabStop+FTabStop}};${nl}`; } +} + /* TODO for(let n = 0 to FCallFunctions.Count - 1 do begin @@ -433,7 +451,7 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo /// /// Determine the modifiers used in the target keyboard and return a bitmask -/// representing them, or an integer value when not in debug mode +/// representing them, or an number value when not in debug mode /// /// @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 */' /// @@ -442,7 +460,7 @@ function GetKeyboardModifierBitmask(source: KMXFile): string { for(let gp of source.keyboard.groups) { if(gp.fUsingKeys) { for(let kp of gp.keys) { - if(!RuleIsExcludedByPlatform(kp)) { + if(!RuleIsExcludedByPlatform(source, kp)) { bitMask |= JavaScript_Shift(kp, fMnemonic); } } @@ -453,7 +471,7 @@ function GetKeyboardModifierBitmask(source: KMXFile): string { ReportError(0, CWARN_DontMixChiralAndNonChiralModifiers, 'This keyboard contains Ctrl,Alt and LCtrl,LAlt,RCtrl,RAlt sets of modifiers. Use only one or the other set for web target.'); } - if(FDebug) { + if(options.debug) { return FormatModifierAsBitflags(bitMask & KMXFile.KMX_MASK_KEYS); // Exclude KMX_ISVIRTUALKEY, KMX_VIRTUALCHARKEY } @@ -469,7 +487,7 @@ function GetKeyboardModifierBitmask(source: KMXFile): string { /// function JavaScript_SetupDebug() { if(IsKeyboardVersion10OrLater()) { - if(FDebug) { + if(options.debug) { return 'var modCodes = keyman.osk.modifierCodes;'+nl+ FTabStop+'var keyCodes = keyman.osk.keyCodes;'+nl; } @@ -512,14 +530,14 @@ function HasSupplementaryPlaneChars() { end; var - I: Integer; + I: number; fsp: PFILE_STORE; fgp: PFILE_GROUP; - j: Integer; + j: number; fkp: PFILE_KEY; begin fsp := fk.dpStoreArray; - for i := 0 to Integer(fk.cxStoreArray) - 1 do + for i := 0 to number(fk.cxStoreArray) - 1 do begin if StringHasSuppChars(fsp.dpString) then Exit(True); @@ -527,10 +545,10 @@ begin end; fgp := fk.dpGroupArray; - for i := 0 to Integer(fk.cxGroupArray) - 1 do + for i := 0 to number(fk.cxGroupArray) - 1 do begin fkp := fgp.dpKeyArray; - for j := 0 to Integer(fgp.cxKeyArray) - 1 do + for j := 0 to number(fgp.cxKeyArray) - 1 do begin if StringHasSuppChars(fkp.dpContext) or StringHasSuppChars(fkp.dpOutput) then @@ -547,4 +565,33 @@ begin Result := False; end;*/ +} + +export function RuleIsExcludedByPlatform(source: KMXFile, fkp: KEY): boolean { + if(fkp.dpContext == null || fkp.dpContext == '') { + return false; + } + + let x = 0; + while(x < fkp.dpContext.length) { + let rec = ExpandSentinel(source.keyboard, fkp.dpContext, x); + if(rec.IsSentinel && + (rec.Code == KMXFile.CODE_IFSYSTEMSTORE) && + (rec.IfSystemStore.dwSystemID == KMXFile.TSS_PLATFORM) && + rec.IfSystemStore.Store.dpString.includes('native')) { + if(rec.IfSystemStore.Store.dpString.match(/windows|desktop|macosx|linux/)) { + return true; + } + } + x = incxstr(fkp.dpContext, x); + } + + return false; +} + +function WriteBeginStatement(source: KMXFile, name: string, groupIndex: number): string { + const fgp = source.keyboard.groups[groupIndex]; + return `${FTabStop}this.${name}=function(t,e) {${nl}`+ + `${FTabStop+FTabStop}return this.g${JavaScript_Name(groupIndex, fgp.dpName)}(t,e);${nl}`+ + `${FTabStop}};${nl}`; } \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/util/util.ts b/developer/src/kmc-kmw/src/util/util.ts index d663fc490b..1c01a22bf5 100644 --- a/developer/src/kmc-kmw/src/util/util.ts +++ b/developer/src/kmc-kmw/src/util/util.ts @@ -1,3 +1,4 @@ +import { STORE, GROUP, KEYBOARD, KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; /** * Verifies that value is an item in the enumeration. @@ -5,3 +6,246 @@ export function isValidEnumValue(enu: T, value: string) { return (Object.values(enu) as string[]).includes(value); } + +export interface TSentinelRecord { + IsSentinel: boolean; + Code?: number; + + Any?: { + StoreIndex: number; + Store: STORE; + }; + Index?: { + StoreIndex: number; + Store: STORE; + Index: number; + }; + DeadKey?: { + DeadKey: number; + }; + Use?: { + GroupIndex: number; + Group: GROUP; + }; + Call?: { + StoreIndex: number; + Store: STORE; + }; + ContextEx?: { + Index: number; + }; + IfOpt?: { + StoreIndex1: number; + Store1: STORE; + StoreIndex2: number; + Store2: STORE; + IsNot: number; + }; + IfSystemStore?: { + dwSystemID: number; + SystemStore: STORE; + StoreIndex: number; + Store: STORE; + IsNot: number; + }; + SetOpt?: { + StoreIndex1: number; + Store1: STORE; + StoreIndex2: number; + Store2: STORE; + }; + SetSystemStore?: { + dwSystemID: number; + SystemStore: STORE; + StoreIndex: number; + Store: STORE; + }; + ResetOpt?: { + StoreIndex: number; + Store: STORE; + }; + SaveOpt?: { + StoreIndex: number; + Store: STORE; + }; + ChrVal?: number; +}; + + +export function ExpandSentinel(fk: KEYBOARD, pwsz: string, x: number): TSentinelRecord { + let result: TSentinelRecord = { + IsSentinel: false + }; + if(pwsz.charCodeAt(x) == KMXFile.UC_SENTINEL) { + result.IsSentinel = true; + x++; + result.Code = pwsz.charCodeAt(x); + x++; + switch(result.Code) { + case KMXFile.CODE_ANY: + case KMXFile.CODE_NOTANY: // I3981 + result.Any.StoreIndex = pwsz.charCodeAt(x) - 1; + result.Any.Store = fk.stores[result.Any.StoreIndex]; + break; + case KMXFile.CODE_INDEX: + result.Index.StoreIndex = pwsz.charCodeAt(x) - 1; + result.Index.Store = fk.stores[result.Index.StoreIndex]; + x++; + result.Index.Index = pwsz.charCodeAt(x); + break; + case KMXFile.CODE_DEADKEY: + result.DeadKey.DeadKey = pwsz.charCodeAt(x) - 1; + break; + case KMXFile.CODE_USE: + result.Use.GroupIndex = pwsz.charCodeAt(x) - 1; + result.Use.Group = fk.groups[result.Use.GroupIndex]; + break; + case KMXFile.CODE_CALL: + result.Call.StoreIndex = pwsz.charCodeAt(x) - 1; + result.Call.Store = fk.stores[result.Call.StoreIndex]; + break; + case KMXFile.CODE_CONTEXTEX: + result.ContextEx.Index = pwsz.charCodeAt(x); + break; + case KMXFile.CODE_SETOPT: // I3429 + result.SetOpt.StoreIndex1 = pwsz.charCodeAt(x) - 1; + result.SetOpt.Store1 = fk.stores[result.SetOpt.StoreIndex1]; + x++; + result.SetOpt.StoreIndex2 = pwsz.charCodeAt(x) - 1; + result.SetOpt.Store2 = fk.stores[result.SetOpt.StoreIndex2]; + break; + case KMXFile.CODE_SETSYSTEMSTORE: // I3437 + result.SetSystemStore.dwSystemID = pwsz.charCodeAt(x) - 1; + result.SetSystemStore.SystemStore = fk.stores.find(s => s.dwSystemID == result.SetSystemStore.dwSystemID) || null; + x++; + result.SetSystemStore.StoreIndex = pwsz.charCodeAt(x) - 1; + result.SetSystemStore.Store = fk.stores[result.SetSystemStore.StoreIndex]; + break; + case KMXFile.CODE_RESETOPT: // I3429 + result.ResetOpt.StoreIndex = pwsz.charCodeAt(x) - 1; + result.ResetOpt.Store = fk.stores[result.ResetOpt.StoreIndex]; + break; + case KMXFile.CODE_SAVEOPT: // I3429 + result.SaveOpt.StoreIndex = pwsz.charCodeAt(x) - 1; + result.SaveOpt.Store = fk.stores[result.SaveOpt.StoreIndex]; + break; + case KMXFile.CODE_IFOPT: // I3429 + result.IfOpt.StoreIndex1 = pwsz.charCodeAt(x) - 1; + result.IfOpt.Store1 = fk.stores[result.IfOpt.StoreIndex1]; + x++; + result.IfOpt.IsNot = pwsz.charCodeAt(x) - 1; // I3429 + x++; + result.IfOpt.StoreIndex2 = pwsz.charCodeAt(x) - 1; + result.IfOpt.Store2 = fk.stores[result.IfOpt.StoreIndex2]; + break; + case KMXFile.CODE_IFSYSTEMSTORE: // I3430 + result.IfSystemStore.dwSystemID = pwsz.charCodeAt(x) - 1; + result.IfSystemStore.SystemStore = fk.stores.find(s => s.dwSystemID == result.IfSystemStore.dwSystemID) || null; + x++; + result.IfSystemStore.IsNot = pwsz.charCodeAt(x) - 1; // I3430 + x++; + result.IfSystemStore.StoreIndex = pwsz.charCodeAt(x) - 1; + result.IfSystemStore.Store = fk.stores[result.IfSystemStore.StoreIndex]; + break; + default: + throw new Error(`Unrecognized system store value ${result.Code}`); + } + } + else { + result.ChrVal = GetSuppChar(pwsz, x); + } + return result; +} + +export function GetSuppChar(p: string, x: number): number { + return p.codePointAt(x); +} + +export function incxstr(p: string, x: number): number { + if(x >= p.length) { + return p.length; + } + + let ch = p.charCodeAt(x); + if(ch != KMXFile.UC_SENTINEL) { + if(ch >= 0xD800 && ch <= 0xDBFF) { + x++; + if(x == p.length) { + return x; + } + ch = p.charCodeAt(x); + if (ch >= 0xDC00 && ch <= 0xDFFF) { + x++; + } + } + else { + x++; + } + return x; + } + + x++; + if(x == p.length) { + return x; + } + + switch(p.charCodeAt(x)) { + case KMXFile.CODE_ANY: x += 2; break; + case KMXFile.CODE_INDEX: x += 3; break; + case KMXFile.CODE_USE: x += 2; break; + case KMXFile.CODE_DEADKEY: x += 2; break; + case KMXFile.CODE_EXTENDED: + x += 3; + while(x <= p.length && p.charCodeAt(x) != KMXFile.UC_SENTINEL_EXTENDEDEND) { + x++; + } + break; + case KMXFile.CODE_CALL: x += 2; break; + case KMXFile.CODE_CONTEXTEX: x += 2; break; + case KMXFile.CODE_NOTANY: x += 2; break; + + case KMXFile.CODE_CLEARCONTEXT: x += 2; break; + case KMXFile.CODE_IFOPT: x += 4; break; + case KMXFile.CODE_IFSYSTEMSTORE: x += 4; break; + case KMXFile.CODE_SETOPT: x += 3; break; + case KMXFile.CODE_SETSYSTEMSTORE: x += 3; break; + case KMXFile.CODE_RESETOPT: x += 2; break; + case KMXFile.CODE_SAVEOPT: x += 2; break; + + default: x++; + } + + if(x >= p.length) { + return p.length; + } + + return x; +} + +export function xstrlen(p: string): number { + let result = 0, x = 0; + while(x < p.length) { + x = incxstr(p, x); + result++; + } + return result; +} + +export function xstrlen_printing(p: string): number { + let result = 0, x = 0; + while(x < p.length) { + if(x + 1 < p.length && p.charCodeAt(x) == KMXFile.UC_SENTINEL) { + switch(p.charCodeAt(x+1)) { + case KMXFile.CODE_DEADKEY: + case KMXFile.CODE_NUL: + case KMXFile.CODE_IFOPT: + case KMXFile.CODE_IFSYSTEMSTORE: + result--; + break; + } + } + x = incxstr(p, x); + result++; + } + return result; +} From 68f97306df2b8275c38e48658777d16c0ff72f4a Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Wed, 3 May 2023 12:27:05 +0700 Subject: [PATCH 05/21] feat: temp commit -- kmw compiler --- common/web/types/src/kmx/kmx-file-reader.ts | 42 +- common/web/types/src/kmx/kmx.ts | 34 +- developer/build.sh | 1 + .../src/common/web/test-helpers/index.ts | 13 +- developer/src/kmc-kmw/package-lock.json | 1789 ++++++ developer/src/kmc-kmw/package.json | 6 +- .../src/kmc-kmw/src/compiler/callbacks.ts | 2 + .../kmc-kmw/src/compiler/compiler-globals.ts | 14 +- .../kmc-kmw/src/compiler/compiler-options.ts | 2 + .../src/compiler/javascript-strings.ts | 965 ++- .../src/compiler/keymanweb-compiler.ts | 81 - .../src/kmc-kmw/src/compiler/messages.ts | 5 +- .../src/compiler/write-compiled-keyboard.ts | 231 +- developer/src/kmc-kmw/src/main.ts | 2 +- developer/src/kmc-kmw/src/util/util.ts | 212 +- developer/src/kmc-kmw/test/README.md | 7 + .../kmc-kmw/test/fixtures/khmer_angkor.ico | Bin 0 -> 1150 bytes .../src/kmc-kmw/test/fixtures/khmer_angkor.js | 5463 +++++++++++++++++ .../fixtures/khmer_angkor.keyman-touch-layout | 1950 ++++++ .../kmc-kmw/test/fixtures/khmer_angkor.kmn | 642 ++ .../kmc-kmw/test/fixtures/khmer_angkor.kvks | 206 + .../src/kmc-kmw/test/test-compiler-manual.ts | 49 + developer/src/kmc-kmw/test/test-compiler.ts | 55 + developer/src/kmc-kmw/test/tsconfig.json | 25 + developer/src/kmc-kmw/tsconfig.json | 4 +- 25 files changed, 11396 insertions(+), 404 deletions(-) create mode 100644 developer/src/kmc-kmw/package-lock.json delete mode 100644 developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts create mode 100644 developer/src/kmc-kmw/test/README.md create mode 100644 developer/src/kmc-kmw/test/fixtures/khmer_angkor.ico create mode 100644 developer/src/kmc-kmw/test/fixtures/khmer_angkor.js create mode 100644 developer/src/kmc-kmw/test/fixtures/khmer_angkor.keyman-touch-layout create mode 100644 developer/src/kmc-kmw/test/fixtures/khmer_angkor.kmn create mode 100644 developer/src/kmc-kmw/test/fixtures/khmer_angkor.kvks create mode 100644 developer/src/kmc-kmw/test/test-compiler-manual.ts create mode 100644 developer/src/kmc-kmw/test/test-compiler.ts create mode 100644 developer/src/kmc-kmw/test/tsconfig.json diff --git a/common/web/types/src/kmx/kmx-file-reader.ts b/common/web/types/src/kmx/kmx-file-reader.ts index 46cfc8eb39..824e56c71d 100644 --- a/common/web/types/src/kmx/kmx-file-reader.ts +++ b/common/web/types/src/kmx/kmx-file-reader.ts @@ -1,4 +1,4 @@ -import { KMXFile, BUILDER_COMP_KEYBOARD, KEYBOARD, STORE } from "./kmx.js"; +import { KMXFile, BUILDER_COMP_KEYBOARD, KEYBOARD, STORE, GROUP, KEY } from "./kmx.js"; import * as r from 'restructure'; export class KmxFileReader { @@ -21,9 +21,18 @@ export class KmxFileReader { return null; } - // TODO: all header fields - let result = new KEYBOARD(); + result.fileVersion = binaryKeyboard.dwFileVersion; + result.flags = binaryKeyboard.dwFlags; + result.hotkey = binaryKeyboard.dwHotKey; + result.keyboardVersion = '0'; //TODO + result.startGroup = { + ansi: binaryKeyboard.StartGroup_ANSI, + unicode: binaryKeyboard.StartGroup_Unicode, + newContext: -1, //TODO + postKeystroke: -1 // TODO + } + let offset = binaryKeyboard.dpStoreArray; for(let i = 0; i < binaryKeyboard.cxStoreArray; i++) { let binaryStore = kmx.COMP_STORE.fromBuffer(source.slice(offset)); @@ -35,7 +44,32 @@ export class KmxFileReader { offset += KMXFile.COMP_STORE_SIZE; } - // TODO: groups + offset = binaryKeyboard.dpGroupArray; + for(let i = 0; i < binaryKeyboard.cxGroupArray; i++) { + let binaryGroup = kmx.COMP_GROUP.fromBuffer(source.slice(offset)); + let group = new GROUP(); + group.dpMatch = this.readString(source, binaryGroup.dpMatch); + group.dpName = this.readString(source, binaryGroup.dpName); + group.dpNoMatch = this.readString(source, binaryGroup.dpNoMatch); + group.fUsingKeys = binaryGroup.fUsingKeys; + group.keys = []; + + let keyOffset = binaryGroup.dpKeyArray; + for(let j = 0; j < binaryGroup.cxKeyArray; j++) { + let binaryKey = kmx.COMP_KEY.fromBuffer(source.slice(keyOffset)); + let key = new KEY(); + key.Key = binaryKey.Key; + key.Line = binaryKey.Line; + key.ShiftFlags = binaryKey.ShiftFlags; + key.dpContext = this.readString(source, binaryKey.dpContext); + key.dpOutput = this.readString(source, binaryKey.dpOutput); + group.keys.push(key); + keyOffset += KMXFile.COMP_KEY_SIZE; + } + + result.groups.push(group); + offset += KMXFile.COMP_GROUP_SIZE; + } // TODO: KMXPlusFile diff --git a/common/web/types/src/kmx/kmx.ts b/common/web/types/src/kmx/kmx.ts index febda9b5e6..cb7af49480 100644 --- a/common/web/types/src/kmx/kmx.ts +++ b/common/web/types/src/kmx/kmx.ts @@ -8,15 +8,15 @@ import * as r from 'restructure'; // kmx-builder will transform these to the corresponding COMP_xxxx export class KEYBOARD { - fileVersion?: number; // dwFileVersion - keyboardVersion?: number; // version + fileVersion?: number; // dwFileVersion (TSS_FILEVERSION) + keyboardVersion?: string; // version (TSS_KEYBOARDVERSION) - startGroup?: { + startGroup: { ansi: number; unicode: number; - newContext: number; - postKeystroke: number; - }; + newContext: number; // TSS_BEGIN_NEWCONTEXT + postKeystroke: number; // TSS_BEGIN_POSTKEYSTROKE + } = {ansi:0xFFFFFFFF, unicode:0xFFFFFFFF, newContext:0xFFFFFFFF, postKeystroke:0xFFFFFFFF}; flags?: number; hotkey?: number; @@ -34,7 +34,7 @@ export class STORE { export class GROUP { dpName: string; - keys: KEY[]; + keys: KEY[] = []; dpMatch: string; dpNoMatch: string; fUsingKeys: boolean; @@ -332,6 +332,21 @@ export class KMXFile { public static readonly ISVIRTUALKEY = 0x4000; // It is a Virtual Key Sequence public static readonly VIRTUALCHARKEY = 0x8000; // Keyman 6.0: Virtual Key Cap Sequence NOT YET + public static readonly MASK_MODIFIER_CHIRAL = KMXFile.LCTRLFLAG | KMXFile.RCTRLFLAG | KMXFile.LALTFLAG | KMXFile.RALTFLAG; + public static readonly MASK_MODIFIER_SHIFT = KMXFile.K_SHIFTFLAG; + public static readonly MASK_MODIFIER_NONCHIRAL = KMXFile.K_CTRLFLAG | KMXFile.K_ALTFLAG; + + public static readonly MASK_STATEKEY = KMXFile.CAPITALFLAG | KMXFile.NOTCAPITALFLAG | + KMXFile.NUMLOCKFLAG | KMXFile.NOTNUMLOCKFLAG | + KMXFile.SCROLLFLAG | KMXFile.NOTSCROLLFLAG; + public static readonly MASK_KEYTYPE = KMXFile.ISVIRTUALKEY | KMXFile.VIRTUALCHARKEY; + + public static readonly MASK_MODIFIER = KMXFile.MASK_MODIFIER_CHIRAL | KMXFile.MASK_MODIFIER_SHIFT | KMXFile.MASK_MODIFIER_NONCHIRAL; + + public static readonly MASK_KEYS = KMXFile.MASK_MODIFIER | KMXFile.MASK_STATEKEY; + public static readonly KMX_MASK_VALID = KMXFile.MASK_KEYS | KMXFile.MASK_KEYTYPE; + + public static readonly K_MODIFIERFLAG = 0x007F; public static readonly K_NOTMODIFIERFLAG = 0xFF00; // I4548 @@ -347,10 +362,7 @@ export class KMXFile { /* In-memory representation of the keyboard */ - public keyboard: KEYBOARD = { - groups: [], - stores: [] - }; + public keyboard: KEYBOARD = new KEYBOARD(); constructor() { diff --git a/developer/build.sh b/developer/build.sh index 76fc3c94a7..0ad6e84bd5 100755 --- a/developer/build.sh +++ b/developer/build.sh @@ -29,6 +29,7 @@ builder_describe \ test \ ":kmcmplib=src/kmcmplib Compiler - .kmn compiler" \ ":kmc-kmn=src/kmc-kmn Compiler - .kmn wrapper Keyboard Module" \ + ":kmc-kmw=src/kmc-kmw Compiler - .kmn Javascript Keyboard Module" \ ":kmc-ldml=src/kmc-ldml Compiler - LDML Keyboard Module" \ ":kmc-model=src/kmc-model Compiler - Lexical Model Module" \ ":kmc-model-info=src/kmc-model-info Compiler - .model_info Module" \ diff --git a/developer/src/common/web/test-helpers/index.ts b/developer/src/common/web/test-helpers/index.ts index e79271227e..7f34107dc9 100644 --- a/developer/src/common/web/test-helpers/index.ts +++ b/developer/src/common/web/test-helpers/index.ts @@ -1,6 +1,6 @@ import * as fs from 'fs'; import * as path from 'path'; -import { CompilerEvent, CompilerCallbacks, CompilerSchema, CompilerPathCallbacks, CompilerFileSystemCallbacks } from '@keymanapp/common-types'; +import { CompilerEvent, CompilerCallbacks, CompilerSchema, CompilerPathCallbacks, CompilerFileSystemCallbacks, compilerErrorSeverityName } from '@keymanapp/common-types'; export { verifyCompilerMessagesObject } from './verifyCompilerMessagesObject.js'; // TODO: schemas are only used by kmc-ldml for now, so this works at this @@ -19,6 +19,17 @@ export class TestCompilerCallbacks implements CompilerCallbacks { this.messages = []; } + printMessages() { + this.messages.forEach(event => { + const code = event.code.toString(16); + if(event.line) { + console.log(`${compilerErrorSeverityName(event.code)} ${code} [${event.line}]: ${event.message}`); + } else { + console.log(`${compilerErrorSeverityName(event.code)} ${code}: ${event.message}`); + } + }); + } + hasMessage(code: number): boolean { return this.messages.find((item) => item.code == code) === undefined ? false : true; } diff --git a/developer/src/kmc-kmw/package-lock.json b/developer/src/kmc-kmw/package-lock.json new file mode 100644 index 0000000000..1a8b017d98 --- /dev/null +++ b/developer/src/kmc-kmw/package-lock.json @@ -0,0 +1,1789 @@ +{ + "name": "@keymanapp/kmc-kmw", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@keymanapp/kmc-kmw", + "license": "MIT", + "dependencies": { + "@keymanapp/keyman-version": "*", + "ajv": "^8.11.0", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "semver": "^7.3.7", + "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" + }, + "devDependencies": { + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.7", + "@types/node": "^10.14.6", + "@types/semver": "^7.3.12", + "@types/xml2js": "^0.4.5", + "c8": "^7.12.0", + "chai": "^4.3.4", + "chalk": "^2.4.2", + "mocha": "^8.4.0", + "ts-node": "^9.1.1", + "typescript": "^4.9.5" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@keymanapp/keyman-version": { + "version": "16.0.139", + "resolved": "https://registry.npmjs.org/@keymanapp/keyman-version/-/keyman-version-16.0.139.tgz", + "integrity": "sha512-hUCgWq+msSTSxra9xOhSxN/nCPxk/hLnPHHTUnFvIc39uxJ/DjNQGkxtsxTdxjCqWZr7frE/2kT7ob9h5Dh5eQ==" + }, + "node_modules/@types/chai": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", + "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", + "dev": true + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, + "node_modules/@types/mocha": { + "version": "5.2.7", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "10.17.60", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, + "node_modules/@types/xml2js": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.11.tgz", + "integrity": "sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@ungap/promise-all-settled": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", + "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", + "dev": true + }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/c8": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.13.0.tgz", + "integrity": "sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^2.0.0", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.1.4", + "rimraf": "^3.0.2", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", + "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.5.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.1" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/diff": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/foreground-child": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true, + "engines": { + "node": ">=4.x" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", + "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha": { + "version": "8.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.1.20", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", + "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", + "dev": true, + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", + "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restructure": { + "version": "3.0.0", + "resolved": "git+ssh://git@github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "integrity": "sha512-2vBFOLc0+dkUb3Pnpl87o+B4SIc3MAm3P8PXT8YFkP51URFGsgTgm3gAnwTX2jXSEd/5eT9n7C733loG6OaVgw==", + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "node_modules/semver": { + "version": "7.3.7", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", + "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-node": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", + "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "dev": true, + "dependencies": { + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "typescript": ">=2.7" + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/workerpool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", + "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "git+ssh://git@github.com/keymanapp/dependency-node-xml2js.git#535fe732dc408d697e0f847c944cc45f0baf0829", + "integrity": "sha512-5CS+yWxp0qg8zO7ng/iXrBZm2FXgpiJ+RJ3E0LzRxDXChESqzazRwzl8sXYe8/7je/NfwG4EXcClaRKUkcIvtQ==", + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/developer/src/kmc-kmw/package.json b/developer/src/kmc-kmw/package.json index e41821bf22..e00a3c7e31 100644 --- a/developer/src/kmc-kmw/package.json +++ b/developer/src/kmc-kmw/package.json @@ -13,6 +13,7 @@ }, "scripts": { "build": "tsc -b", + "tsc": "tsc", "test": "cd test && tsc -b && cd .. && c8 mocha", "prepublishOnly": "npm run build" }, @@ -22,7 +23,7 @@ "url": "https://github.com/keymanapp/keyman/issues" }, "dependencies": { - "@keymanapp/keyman-version": "*", + "@keymanapp/common-types": "*", "ajv": "^8.11.0", "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", "semver": "^7.3.7", @@ -39,7 +40,8 @@ "chalk": "^2.4.2", "mocha": "^8.4.0", "ts-node": "^9.1.1", - "typescript": "4.6.3" + "typescript": "^4.9.5", + "@keymanapp/kmc-kmn": "*" }, "mocha": { "spec": "build/test/**/test-*.js", diff --git a/developer/src/kmc-kmw/src/compiler/callbacks.ts b/developer/src/kmc-kmw/src/compiler/callbacks.ts index c20a2b078c..bdc7a17464 100644 --- a/developer/src/kmc-kmw/src/compiler/callbacks.ts +++ b/developer/src/kmc-kmw/src/compiler/callbacks.ts @@ -10,3 +10,5 @@ export default interface CompilerCallbacks { loadKvksJsonSchema(): Buffer; reportMessage(event: CompilerEvent): void; }; + +// TODO: eliminate this \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/compiler-globals.ts b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts index 067fea1d51..bb4874a559 100644 --- a/developer/src/kmc-kmw/src/compiler/compiler-globals.ts +++ b/developer/src/kmc-kmw/src/compiler/compiler-globals.ts @@ -1,14 +1,16 @@ -import { KEYBOARD, KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; +import { KMX, CompilerCallbacks } from "@keymanapp/common-types"; import CompilerOptions from "./compiler-options.js"; export let FTabStop: string; export let nl: string; export let FCompilerWarningsAsErrors = false; -export let fk: KEYBOARD; +export let fk: KMX.KEYBOARD; export let FMnemonic: boolean; export let options: CompilerOptions; +export let callbacks: CompilerCallbacks; -export function setupGlobals(_options: CompilerOptions, _tab: string, _nl: string, _keyboard: KEYBOARD) { +export function setupGlobals(_callbacks: CompilerCallbacks, _options: CompilerOptions, _tab: string, _nl: string, _keyboard: KMX.KEYBOARD) { + callbacks = _callbacks; options = _options; FTabStop = _tab; nl = _nl; @@ -16,13 +18,13 @@ export function setupGlobals(_options: CompilerOptions, _tab: string, _nl: strin } export function IsKeyboardVersion10OrLater(): boolean { - return fk.fileVersion >= KMXFile.VERSION_100; + return fk.fileVersion >= KMX.KMXFile.VERSION_100; } export function IsKeyboardVersion14OrLater(): boolean { - return fk.fileVersion >= KMXFile.VERSION_140; + return fk.fileVersion >= KMX.KMXFile.VERSION_140; } export function IsKeyboardVersion15OrLater(): boolean { - return fk.fileVersion >= KMXFile.VERSION_150; + return fk.fileVersion >= KMX.KMXFile.VERSION_150; } diff --git a/developer/src/kmc-kmw/src/compiler/compiler-options.ts b/developer/src/kmc-kmw/src/compiler/compiler-options.ts index 76dd4b5ba4..bcb99c5d43 100644 --- a/developer/src/kmc-kmw/src/compiler/compiler-options.ts +++ b/developer/src/kmc-kmw/src/compiler/compiler-options.ts @@ -11,3 +11,5 @@ export default interface CompilerOptions { */ addCompilerVersion: boolean; }; + +// TODO: we have a shared CompilerOptions intf, eliminate this \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts index eaf31a08a3..b4ae08829d 100644 --- a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts +++ b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts @@ -1,17 +1,21 @@ -import { TSentinelRecord, GetSuppChar, ExpandSentinel, incxstr, xstrlen, xstrlen_printing } from "src/util/util.js"; -import { GROUP, KEY, KEYBOARD, KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; +import { TSentinelRecord, GetSuppChar, ExpandSentinel, incxstr, xstrlen, xstrlen_printing } from "../util/util.js"; +import { KMX } from "@keymanapp/common-types"; -import { FMnemonic, FTabStop, IsKeyboardVersion10OrLater, nl, options } from "./compiler-globals.js"; -import { CERR_InvalidBegin, CERR_NotSupportedInKeymanWebContext, CERR_VirtualCharacterKeysNotSupportedInKeymanWeb, CERR_VirtualKeysNotValidForMnemonicLayouts, CHINT_UnreachableKeyCode, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, CWARN_OptionStoreNameInvalid, ReportError } from "./messages.js"; -import { FFix183_LadderLength, RuleIsExcludedByPlatform } from "./write-compiled-keyboard.js"; +import { FMnemonic, FTabStop, IsKeyboardVersion10OrLater, IsKeyboardVersion14OrLater, nl, options } from "./compiler-globals.js"; +import { CERR_NotSupportedInKeymanWebContext, CERR_NotSupportedInKeymanWebOutput, CERR_NotSupportedInKeymanWebStore, CERR_VirtualCharacterKeysNotSupportedInKeymanWeb, CERR_VirtualKeysNotValidForMnemonicLayouts, CHINT_UnreachableKeyCode, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, CWARN_OptionStoreNameInvalid, ReportError } from "./messages.js"; +import { FFix183_LadderLength, FormatModifierAsBitflags, RuleIsExcludedByPlatform } from "./write-compiled-keyboard.js"; -//const SValidIdentifierCharSet = '123'; +const SValidIdentifierCharSet = /[A-Za-z0-9_]/; + +// TODO: lifecycle +let FUnreachableKeys: KMX.KEY[] = []; +let FCallFunctions: string[] = []; export function JavaScript_Name(i: number, pwszName: string, KeepNameForPersistentStorage: boolean = false): string { // I3659 let FChanged: boolean = false; let p = pwszName; - if((pwszName == null || pwszName == undefined || pwszName == '') || (!isFDebug && !KeepNameForPersistentStorage)) { // I3659 // I3681 + if((pwszName == null || pwszName == undefined || pwszName == '') || (!options.debug && !KeepNameForPersistentStorage)) { // I3659 // I3681 return i.toString(10); // for uniqueness } else { @@ -20,7 +24,7 @@ export function JavaScript_Name(i: number, pwszName: string, KeepNameForPersiste : '_'; // Ensures we cannot overlap numbered instances while(p.length) { let ch = p.charAt(0); - if(SValidIdentifierCharSet.includes(ch)) { // I3681 + if(SValidIdentifierCharSet.test(ch)) { // I3681 result += ch; } else { result += '_'; @@ -44,16 +48,16 @@ export function JavaScript_Name(i: number, pwszName: string, KeepNameForPersiste } } -export function JavaScript_Store(fk: KEYBOARD, line: number, pwsz: string): string { +export function JavaScript_Store(fk: KMX.KEYBOARD, line: number, pwsz: string): string { let ch: number, rec: TSentinelRecord, result: string; - const wcsentinel: string = '\uFFFF'; + const wcsentinel: string = String.fromCharCode(KMX.KMXFile.UC_SENTINEL); let n = pwsz.indexOf(wcsentinel); // Start: plain text store. Always use for < 10.0, conditionally for >= 10.0. - if(n == 0 || !IsKeyboardVersion10OrLater) { + if(n < 0 || !IsKeyboardVersion10OrLater()) { result = '"'; while(pwsz.length) { - if(pwsz.charCodeAt(0) == KMXFile.UC_SENTINEL) { + if(pwsz.charCodeAt(0) == KMX.KMXFile.UC_SENTINEL) { result += '.'; // UC_SENTINEL values are not supported in stores for KMW < 10.0. } else { ch = GetSuppChar(pwsz, 0); @@ -70,16 +74,17 @@ export function JavaScript_Store(fk: KEYBOARD, line: number, pwsz: string): stri } else { result = '['; - while(pwsz.length) { + let x = 0; + while(x < pwsz.length) { if(result != '[') { result += ','; } - rec = ExpandSentinel(fk, pwsz, 0); + rec = ExpandSentinel(fk, pwsz, x); if(rec.IsSentinel) { - if(rec.Code == KMXFile.CODE_DEADKEY) { + if(rec.Code == KMX.KMXFile.CODE_DEADKEY) { result += `{t:'d',d:${rec.DeadKey.DeadKey}}`; } - else if(rec.Code == KMXFile.CODE_BEEP) { + else if(rec.Code == KMX.KMXFile.CODE_BEEP) { result += `{t:'b'}`; } else { //if rec.Code = CODE_EXTENDED then @@ -94,7 +99,7 @@ export function JavaScript_Store(fk: KEYBOARD, line: number, pwsz: string): stri // end; } else { - ch = GetSuppChar(pwsz, 0); + ch = GetSuppChar(pwsz, x); result += '"'; // TODO: Refactor the section below into JavaScript_String, as it's // quite common in our code base. @@ -104,7 +109,7 @@ export function JavaScript_Store(fk: KEYBOARD, line: number, pwsz: string): stri result += JavaScript_String(ch) + '"'; // I2242 } - pwsz = pwsz.substring(1); + x = incxstr(pwsz, x); } result += ']'; } @@ -119,9 +124,9 @@ export function JavaScript_String(ch: number): string { // I2242 case 13: return '\\r'; } if(ch < 9) { - return '\\x0'+ch.toString(16); + return '\\x0'+ch.toString(16).toUpperCase(); } else { - return '\\x'+ch.toString(16); + return '\\x'+ch.toString(16).toUpperCase(); } } else { @@ -129,8 +134,35 @@ export function JavaScript_String(ch: number): string { // I2242 } } -export function JavaScript_Rules(fgp: GROUP): string { - let IsEqualKey = function(k1: KEY, k2: KEY): boolean { +function JavaScript_Rule(FTabStops: string, FElse: string, fk: KMX.KEYBOARD, fgp: KMX.GROUP, fkp: KMX.KEY): string { + let predicate: string = '1', linecomment: string = '', FIndent: string; + let result = ''; + + if(fkp.Line > 0 && options.debug) { // I4384 + linecomment = ' // Line '+fkp.Line.toString(); // I4373 + } + + if(xstrlen(fkp.dpContext) > 0) { + predicate = JavaScript_ContextMatch(fk, fkp, fkp.dpContext); + } + + FIndent = FTabStops+FTabStop; + result = `${FTabStops}${FElse}if(${predicate}){${nl}`; + + if(fgp.fUsingKeys) { + result += `${FIndent}r=m=1;${linecomment}${JavaScript_OutputString(fk, FIndent, fkp, fkp.dpOutput, fgp)}`; // I1959 // I3681 + } + else { + result += `${FIndent}m=1;${linecomment}${JavaScript_OutputString(fk, FIndent, fkp, fkp.dpOutput, fgp)}`; // I1959 // I3681 + } + + result += `${nl}${FTabStops}}${nl}`; + return result; +} + + +export function JavaScript_Rules(keyboard: KMX.KEYBOARD, fMnemonic: boolean, fgp: KMX.GROUP): string { + let IsEqualKey = function(k1: KMX.KEY, k2: KMX.KEY): boolean { return ( (JavaScript_Key(k1, FMnemonic) == JavaScript_Key(k2, FMnemonic)) && (JavaScript_Shift(k1, FMnemonic) == JavaScript_Shift(k2, FMnemonic)) @@ -148,8 +180,8 @@ export function JavaScript_Rules(fgp: GROUP): string { let j = 0; let Counter = 0; while(j < fgp.keys.length) { // I1964 - if(!processed_rule[j] && !RuleIsExcludedByPlatform(fkp)) { - let fkp = fgp.keys[j]; + let fkp = fgp.keys[j]; + if(!processed_rule[j] && !RuleIsExcludedByPlatform(keyboard, fkp)) { // Break down by key code // We know the rules are sorted by context length and then key code. // First pass, break the grouping down by key code. @@ -168,9 +200,9 @@ export function JavaScript_Rules(fgp: GROUP): string { let LocalCounter = 0; while (j < fgp.keys.length) { fkp = fgp.keys[j]; - if (!processed_rule[j] && !RuleIsExcludedByPlatform(fkp) && IsEqualKey(fkp, fkp2)) { + if (!processed_rule[j] && !RuleIsExcludedByPlatform(keyboard, fkp) && IsEqualKey(fkp, fkp2)) { processed_rule[j] = true; - result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, LocalHasRules ? 'else ' : '', fgp, fkp); + result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, LocalHasRules ? 'else ' : '', keyboard, fgp, fkp); LocalCounter++; if (FFix183_LadderLength != 0 && (LocalCounter % FFix183_LadderLength) == 0) { @@ -188,7 +220,7 @@ export function JavaScript_Rules(fgp: GROUP): string { } else { // TODO: context character level switches instead of full context comparisons - result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, HasRules ? 'else ' : '', fgp, fkp); + result += JavaScript_Rule(FTabStop + FTabStop + FTabStop, HasRules ? 'else ' : '', keyboard, fgp, fkp); HasRules = true; Counter++; j++; @@ -207,14 +239,42 @@ export function JavaScript_Rules(fgp: GROUP): string { return result; } -export function JavaScript_Shift(fkp: KEY, FMnemonic: boolean): number { +const + USEnglishUnshift: string = ' `' + '1234567890' + '-' + '=' + 'qwertyuiop' + '[' + ']' + '\\' + 'asdfghjkl' + ';' + '\'' + 'zxcvbnm' + ',' + '.' + '/', + USEnglishShift: string = 0xFF + '~' + '!@#$%^&*()' + '_' + '+' + 'QWERTYUIOP' + '{' + '}' + '|' + 'ASDFGHJKL' + ':' + '"' + 'ZXCVBNM' + '<' + '>' + '?', + USEnglishValues: string = 0x20 + 0xc0 + '1234567890' + 0xbd + 0xbb + 'QWERTYUIOP' + 0xdb + 0xdd + 0xdc + 'ASDFGHJKL' + 0xba + 0xde + 'ZXCVBNM' + 0xbc + 0xbe + 0xbf, + UnreachableKeyCodes: number[] = [ // I4141 + 0x00, // &H0 + 0x01, //VK_LBUTTON, // &H1 + 0x02, //VK_RBUTTON, // &H2 + 0x03, //VK_CANCEL, // &H3 + 0x04, //VK_MBUTTON, // &H4 + 0x05, // &H5 + 0x06, // &H6 + 0x07, // &H7 + 0x0A, // &HA + 0x0B, // &HB + 0x0E, // &HE + 0x0F, // &HF + 0x10, //VK_SHIFT, // &H10 + 0x11, //VK_CONTROL, // &H11 + 0x12, //VK_MENU, // &H12 + 0x13, //VK_PAUSE, // &H13 + 0x14, //VK_CAPITAL, // &H14 + 0x1B, //VK_ESCAPE, // &H1B + + 0x90, //VK_NUMLOCK, // &H90 + 0x91 //VK_SCROLL // &H91 + ]; + +export function JavaScript_Shift(fkp: KMX.KEY, FMnemonic: boolean): number { if (FMnemonic) { - if (fkp.ShiftFlags & KMXFile.VIRTUALCHARKEY) { + if (fkp.ShiftFlags & KMX.KMXFile.VIRTUALCHARKEY) { ReportError(fkp.Line, CERR_VirtualCharacterKeysNotSupportedInKeymanWeb, 'Virtual character keys not currently supported in KeymanWeb'); // I1971 // I4061 return 0; } - if (fkp.ShiftFlags & KMXFile.ISVIRTUALKEY && fkp.Key <= 255) { + if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY && fkp.Key <= 255) { // We prohibit K_ keys for mnemonic layouts. We don't block T_ and U_ keys. // TODO: this doesn't resolve the issue of, e.g. SHIFT+K_SPACE // https://github.com/keymanapp/keyman/issues/265 @@ -223,27 +283,27 @@ export function JavaScript_Shift(fkp: KEY, FMnemonic: boolean): number { } } - if (fkp.ShiftFlags & KMXFile.ISVIRTUALKEY) { + if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) { if(IsKeyboardVersion10OrLater()) { // Full chiral modifier and state key support starts with KeymanWeb 10.0 return fkp.ShiftFlags; } // Non-chiral support only and no support for state keys - if (fkp.ShiftFlags & (KMXFile.LCTRLFLAG | KMXFile.RCTRLFLAG | KMXFile.LALTFLAG | KMXFile.RALTFLAG)) { // I4118 + if (fkp.ShiftFlags & (KMX.KMXFile.LCTRLFLAG | KMX.KMXFile.RCTRLFLAG | KMX.KMXFile.LALTFLAG | KMX.KMXFile.RALTFLAG)) { // I4118 ReportError(fkp.Line, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, 'Extended shift flags LALT, RALT, LCTRL, RCTRL are not supported in KeymanWeb'); } if (fkp.ShiftFlags & ( - KMXFile.CAPITALFLAG | KMXFile.NOTCAPITALFLAG | KMXFile.NUMLOCKFLAG | KMXFile.NOTNUMLOCKFLAG | - KMXFile.SCROLLFLAG | KMXFile.NOTSCROLLFLAG)) { // I4118 + KMX.KMXFile.CAPITALFLAG | KMX.KMXFile.NOTCAPITALFLAG | KMX.KMXFile.NUMLOCKFLAG | KMX.KMXFile.NOTNUMLOCKFLAG | + KMX.KMXFile.SCROLLFLAG | KMX.KMXFile.NOTSCROLLFLAG)) { // I4118 ReportError(fkp.Line, CWARN_ExtendedShiftFlagsNotSupportedInKeymanWeb, 'Extended shift flags CAPS and NCAPS are not supported in KeymanWeb'); } - return KMXFile.ISVIRTUALKEY | (fkp.ShiftFlags & (KMXFile.K_SHIFTFLAG | KMXFile.K_CTRLFLAG | KMXFile.K_ALTFLAG)); + return KMX.KMXFile.ISVIRTUALKEY | (fkp.ShiftFlags & (KMX.KMXFile.K_SHIFTFLAG | KMX.KMXFile.K_CTRLFLAG | KMX.KMXFile.K_ALTFLAG)); } - return USEnglishShift.includes(fkp.Key) ? KMXFile.ISVIRTUALKEY | KMXFile.K_SHIFTFLAG : KMXFile.ISVIRTUALKEY; + return USEnglishShift.includes(String.fromCharCode(fkp.Key)) ? KMX.KMXFile.ISVIRTUALKEY | KMX.KMXFile.K_SHIFTFLAG : KMX.KMXFile.ISVIRTUALKEY; } /** @@ -257,19 +317,364 @@ export function JavaScript_Shift(fkp: KEY, FMnemonic: boolean): number { * 'modCodes.SHIFT | modCodes.CAPS | modCodes.VIRTUAL_KEY /* 0x4110 * /' or * '16656' */ -export function JavaScript_ShiftAsString(fkp: KEY, FMnemonic: boolean): string { +export function JavaScript_ShiftAsString(fkp: KMX.KEY, FMnemonic: boolean): string { if(!options.debug) { return JavaScript_Shift(fkp, FMnemonic).toString(); } return ' '+FormatModifierAsBitflags(JavaScript_Shift(fkp, FMnemonic)); } +const VKeyNames = [ // from vkeys.h +// Key Codes +"K_?00", // &H0 +"K_LBUTTON", // &H1 +"K_RBUTTON", // &H2 +"K_CANCEL", // &H3 +"K_MBUTTON", // &H4 +"K_?05", // &H5 +"K_?06", // &H6 +"K_?07", // &H7 +"K_BKSP", // &H8 +"K_TAB", // &H9 +"K_?0A", // &HA +"K_?0B", // &HB +"K_KP5", // &HC +"K_ENTER", // &HD +"K_?0E", // &HE +"K_?0F", // &HF +"K_SHIFT", // &H10 +"K_CONTROL", // &H11 +"K_ALT", // &H12 +"K_PAUSE", // &H13 +"K_CAPS", // &H14 +"K_KANJI?15", // &H15 +"K_KANJI?16", // &H16 +"K_KANJI?17", // &H17 +"K_KANJI?18", // &H18 +"K_KANJI?19", // &H19 +"K_?1A", // &H1A +"K_ESC", // &H1B +"K_KANJI?1C", // &H1C +"K_KANJI?1D", // &H1D +"K_KANJI?1E", // &H1E +"K_KANJI?1F", // &H1F +"K_SPACE", // &H20 +"K_PGUP", // &H21 +"K_PGDN", // &H22 +"K_END", // &H23 +"K_HOME", // &H24 +"K_LEFT", // &H25 +"K_UP", // &H26 +"K_RIGHT", // &H27 +"K_DOWN", // &H28 +"K_SEL", // &H29 +"K_PRINT", // &H2A +"K_EXEC", // &H2B +"K_PRTSCN", // &H2C +"K_INS", // &H2D +"K_DEL", // &H2E +"K_HELP", // &H2F +"K_0", // &H30 +"K_1", // &H31 +"K_2", // &H32 +"K_3", // &H33 +"K_4", // &H34 +"K_5", // &H35 +"K_6", // &H36 +"K_7", // &H37 +"K_8", // &H38 +"K_9", // &H39 +"K_?3A", // &H3A +"K_?3B", // &H3B +"K_?3C", // &H3C +"K_?3D", // &H3D +"K_?3E", // &H3E +"K_?3F", // &H3F +"K_?40", // &H40 +"K_A", // &H41 +"K_B", // &H42 +"K_C", // &H43 +"K_D", // &H44 +"K_E", // &H45 +"K_F", // &H46 +"K_G", // &H47 +"K_H", // &H48 +"K_I", // &H49 +"K_J", // &H4A +"K_K", // &H4B +"K_L", // &H4C +"K_M", // &H4D +"K_N", // &H4E +"K_O", // &H4F +"K_P", // &H50 +"K_Q", // &H51 +"K_R", // &H52 +"K_S", // &H53 +"K_T", // &H54 +"K_U", // &H55 +"K_V", // &H56 +"K_W", // &H57 +"K_X", // &H58 +"K_Y", // &H59 +"K_Z", // &H5A +"K_?5B", // &H5B +"K_?5C", // &H5C +"K_?5D", // &H5D +"K_?5E", // &H5E +"K_?5F", // &H5F +"K_NP0", // &H60 +"K_NP1", // &H61 +"K_NP2", // &H62 +"K_NP3", // &H63 +"K_NP4", // &H64 +"K_NP5", // &H65 +"K_NP6", // &H66 +"K_NP7", // &H67 +"K_NP8", // &H68 +"K_NP9", // &H69 +"K_NPSTAR", // &H6A +"K_NPPLUS", // &H6B +"K_SEPARATOR", // &H6C +"K_NPMINUS", // &H6D +"K_NPDOT", // &H6E +"K_NPSLASH", // &H6F +"K_F1", // &H70 +"K_F2", // &H71 +"K_F3", // &H72 +"K_F4", // &H73 +"K_F5", // &H74 +"K_F6", // &H75 +"K_F7", // &H76 +"K_F8", // &H77 +"K_F9", // &H78 +"K_F10", // &H79 +"K_F11", // &H7A +"K_F12", // &H7B +"K_F13", // &H7C +"K_F14", // &H7D +"K_F15", // &H7E +"K_F16", // &H7F +"K_F17", // &H80 +"K_F18", // &H81 +"K_F19", // &H82 +"K_F20", // &H83 +"K_F21", // &H84 +"K_F22", // &H85 +"K_F23", // &H86 +"K_F24", // &H87 -function JavaScript_Key(fkp: KEY, FMnemonic: boolean): number { +"K_?88", // &H88 +"K_?89", // &H89 +"K_?8A", // &H8A +"K_?8B", // &H8B +"K_?8C", // &H8C +"K_?8D", // &H8D +"K_?8E", // &H8E +"K_?8F", // &H8F + +"K_NUMLOCK", // &H90 +"K_SCROLL", // &H91 + +"K_?92", // &H92 +"K_?93", // &H93 +"K_?94", // &H94 +"K_?95", // &H95 +"K_?96", // &H96 +"K_?97", // &H97 +"K_?98", // &H98 +"K_?99", // &H99 +"K_?9A", // &H9A +"K_?9B", // &H9B +"K_?9C", // &H9C +"K_?9D", // &H9D +"K_?9E", // &H9E +"K_?9F", // &H9F +"K_?A0", // &HA0 +"K_?A1", // &HA1 +"K_?A2", // &HA2 +"K_?A3", // &HA3 +"K_?A4", // &HA4 +"K_?A5", // &HA5 +"K_?A6", // &HA6 +"K_?A7", // &HA7 +"K_?A8", // &HA8 +"K_?A9", // &HA9 +"K_?AA", // &HAA +"K_?AB", // &HAB +"K_?AC", // &HAC +"K_?AD", // &HAD +"K_?AE", // &HAE +"K_?AF", // &HAF +"K_?B0", // &HB0 +"K_?B1", // &HB1 +"K_?B2", // &HB2 +"K_?B3", // &HB3 +"K_?B4", // &HB4 +"K_?B5", // &HB5 +"K_?B6", // &HB6 +"K_?B7", // &HB7 +"K_?B8", // &HB8 +"K_?B9", // &HB9 + +"K_COLON", // &HBA +"K_EQUAL", // &HBB +"K_COMMA", // &HBC +"K_HYPHEN", // &HBD +"K_PERIOD", // &HBE +"K_SLASH", // &HBF +"K_BKQUOTE", // &HC0 + +"K_?C1", // &HC1 +"K_?C2", // &HC2 +"K_?C3", // &HC3 +"K_?C4", // &HC4 +"K_?C5", // &HC5 +"K_?C6", // &HC6 +"K_?C7", // &HC7 +"K_?C8", // &HC8 +"K_?C9", // &HC9 +"K_?CA", // &HCA +"K_?CB", // &HCB +"K_?CC", // &HCC +"K_?CD", // &HCD +"K_?CE", // &HCE +"K_?CF", // &HCF +"K_?D0", // &HD0 +"K_?D1", // &HD1 +"K_?D2", // &HD2 +"K_?D3", // &HD3 +"K_?D4", // &HD4 +"K_?D5", // &HD5 +"K_?D6", // &HD6 +"K_?D7", // &HD7 +"K_?D8", // &HD8 +"K_?D9", // &HD9 +"K_?DA", // &HDA + +"K_LBRKT", // &HDB +"K_BKSLASH", // &HDC +"K_RBRKT", // &HDD +"K_QUOTE", // &HDE +"K_oDF", // &HDF +"K_oE0", // &HE0 +"K_oE1", // &HE1 +"K_oE2", // &HE2 +"K_oE3", // &HE3 +"K_oE4", // &HE4 + +"K_?E5", // &HE5 + +"K_oE6", // &HE6 + +"K_?E7", // &HE7 +"K_?E8", // &HE8 + +"K_oE9", // &HE9 +"K_oEA", // &HEA +"K_oEB", // &HEB +"K_oEC", // &HEC +"K_oED", // &HED +"K_oEE", // &HEE +"K_oEF", // &HEF +"K_oF0", // &HF0 +"K_oF1", // &HF1 +"K_oF2", // &HF2 +"K_oF3", // &HF3 +"K_oF4", // &HF4 +"K_oF5", // &HF5 + +"K_?F6", // &HF6 +"K_?F7", // &HF7 +"K_?F8", // &HF8 +"K_?F9", // &HF9 +"K_?FA", // &HFA +"K_?FB", // &HFB +"K_?FC", // &HFC +"K_?FD", // &HFD +"K_?FE", // &HFE +"K_?FF" // &HFF +]; + +const enum + TKeymanWebTouchStandardKey { + K_LOPT = 50001, + K_ROPT = 50002, + K_NUMERALS = 50003, + K_SYMBOLS = 50004, + K_CURRENCIES = 50005, + K_UPPER = 50006, + K_LOWER = 50007, + K_ALPHA = 50008, + K_SHIFTED = 50009, + K_ALTGR = 50010, + K_TABBACK = 50011, + K_TABFWD = 50012 + }; + +function FormatKeyForErrorMessage(fkp: KMX.KEY, FMnemonic: boolean): string { + function FormatShift(ShiftFlags: number): string { + const + mask: string[] = [ + 'LCTRL', // 0X0001 + 'RCTRL', // 0X0002 + 'LALT', // 0X0004 + 'RALT', // 0X0008 + + 'SHIFT', // 0X0010 + 'CTRL', // 0X0020 + 'ALT', // 0X0040 + + '???', // Reserved + + 'CAPS', // 0X0100 + 'NCAPS', // 0X0200 + + 'NUMLOCK', // 0X0400 + 'NNUMLOCK', // 0X0800 + + 'SCROLLLOCK', // 0X1000 + 'NSCROLLLOCK' // 0X2000 + ]; + + let result = ''; + for(let i = 0; i < mask.length; i++) { + if(ShiftFlags & (1 << i)) { + result += mask[i] + ' '; + } + } + return result; + } + + let result: string; + if(!FMnemonic) { + if (fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) { + if(fkp.Key < 256) { + result = `[${FormatShift(fkp.ShiftFlags)}${VKeyNames[fkp.Key]}]`; + } + else { + result = `[${FormatShift(fkp.ShiftFlags)}K_${fkp.Key.toString(16).toUpperCase()}]`; + } + } + else { + result = `'${String.fromCharCode(fkp.Key)}'`; + } + } + else { + if (fkp.ShiftFlags & KMX.KMXFile.VIRTUALCHARKEY) { + result = `[${FormatShift(fkp.ShiftFlags)}'${String.fromCharCode(fkp.Key)}']`; + } + else { + result = `'${String.fromCharCode(fkp.Key)}'`; + } + } + return result; +} + +function JavaScript_Key(fkp: KMX.KEY, FMnemonic: boolean): number { let Result: number; if(!FMnemonic) { - if(fkp.ShiftFlags & KMXFile.ISVIRTUALKEY) { + if(fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) { Result = fkp.Key; } else { @@ -296,7 +701,7 @@ function JavaScript_Key(fkp: KEY, FMnemonic: boolean): number { Result = 0; } - if (Result == 0 || Result >= Ord(Low(TKeymanWebTouchStandardKey))) { // I4141 + if (Result == 0 || Result >= TKeymanWebTouchStandardKey.K_LOPT) { // I4141 if(!FUnreachableKeys.includes(fkp)) { ReportError(fkp.Line, CHINT_UnreachableKeyCode, 'The rule will never be matched for key '+ @@ -316,7 +721,7 @@ function JavaScript_Key(fkp: KEY, FMnemonic: boolean): number { /// /// @return string representation of the key value, e.g. 'keyCodes.K_A /* 0x41 */' or '65' /// -export function JavaScript_KeyAsString(fkp: KEY, FMnemonic: boolean): string { +export function JavaScript_KeyAsString(fkp: KMX.KEY, FMnemonic: boolean): string { if(options.debug) { return ' '+FormatKeyAsString(JavaScript_Key(fkp, FMnemonic)); } else { @@ -324,7 +729,7 @@ export function JavaScript_KeyAsString(fkp: KEY, FMnemonic: boolean): string { } } -export function JavaScript_ContextMatch(fk: KEYBOARD, fkp: KEY, context: string): string { +export function JavaScript_ContextMatch(fk: KMX.KEYBOARD, fkp: KMX.KEY, context: string): string { if(IsKeyboardVersion10OrLater()) { return JavaScript_FullContextValue(fk, fkp, context); } @@ -333,8 +738,44 @@ export function JavaScript_ContextMatch(fk: KEYBOARD, fkp: KEY, context: string) } } +function JavaScript_ContextLength(Context: string): number { + return xstrlen_printing(Context); +} + +const + KMXCodeNames: string[] = [ + '', + 'any', 'index', 'context', 'nul', 'use', 'return', 'beep', 'deadkey', + '', + 'extended', '', 'switch', 'key', 'clearcontext', 'call', + '', 'contextex', 'notany', + 'set', 'if', 'save', 'reset', // I3429 + 'if(&system)', 'set(&system)']; // I3430 // I3437 + +function GetCodeName(code: number): string { + if (code >= 0 && code < KMXCodeNames.length && KMXCodeNames[code] != '') { + return KMXCodeNames[code]; + } + return code.toString(); +} + +function CheckStoreForInvalidFunctions(fk: KMX.KEYBOARD, key: KMX.KEY, store: KMX.STORE) { // I1520 + let n: number, rec: TSentinelRecord; + const wcsentinel = String.fromCharCode(0xFFFF); + + n = store.dpString.indexOf(wcsentinel); + + // Disable the check with versions >= 10.0, since we now support deadkeys in stores. + if (n >= 0 && !IsKeyboardVersion10OrLater) { + rec = ExpandSentinel(fk, store.dpString, n); + ReportError(key.Line, CERR_NotSupportedInKeymanWebStore, + `${GetCodeName(rec.Code)} is not currently supported in store '${store.dpName}' when used by any or index`); + } +} + + // Used when targeting versions prior to 10.0, before the introduction of FullContextMatch/KFCM. -function JavaScript_CompositeContextValue(fk: KEYBOARD, fkp: KEY, pwsz: string): string { +function JavaScript_CompositeContextValue(fk: KMX.KEYBOARD, fkp: KMX.KEY, pwsz: string): string { // Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions // var // StartQuotes, Len, Cur: Integer; @@ -360,35 +801,35 @@ function JavaScript_CompositeContextValue(fk: KEYBOARD, fkp: KEY, pwsz: string): } switch(rec.Code) { - case KMXFile.CODE_ANY: - CheckStoreForInvalidFunctions(fkp, rec.Any.Store); // I1520 + case KMX.KMXFile.CODE_ANY: + CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520 Result += `k.KA(${Cur},k.KC(${Len-Cur},1,t),this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)})`; break; - case KMXFile.CODE_DEADKEY: + case KMX.KMXFile.CODE_DEADKEY: Result += `k.KDM(${Len-Cur},t,${rec.DeadKey.DeadKey})`; Cur--; // don't increment on deadkeys -- correlates with AdjustIndex function // I3910 break; - case KMXFile.CODE_NUL: // I2243 + case KMX.KMXFile.CODE_NUL: // I2243 Result += `k.KN(${Len-Cur},t)`; Cur--; // don't increment on nul -- correlates with AdjustIndex function // I3910 break; - case KMXFile.CODE_IFOPT: // I3429 + case KMX.KMXFile.CODE_IFOPT: // I3429 Result += `this.s${JavaScript_Name(rec.IfOpt.StoreIndex1, rec.IfOpt.Store1.dpName)}`+ `${rec.IfOpt.IsNot == 0 ? '!==':'==='}`+ `this.s${JavaScript_Name(rec.IfOpt.StoreIndex2,rec.IfOpt.Store2.dpName)}`; // I3429 // I3659 // I3681 Cur--; // don't increment on ifopt -- correlates with AdjustIndex function // I3910 break; - case KMXFile.CODE_IFSYSTEMSTORE: // I3430 + case KMX.KMXFile.CODE_IFSYSTEMSTORE: // I3430 Result += `${rec.IfSystemStore.IsNot == 0 ? '!' : ''}`+ `k.KIFS(${rec.IfSystemStore.dwSystemID},`+ `this.s${JavaScript_Name(rec.IfSystemStore.StoreIndex,rec.IfSystemStore.Store.dpName)},t)`; Cur--; // don't increment on ifsystemstore -- correlates with AdjustIndex function // I3910 break; - case KMXFile.CODE_CONTEXTEX: // I3980 + case KMX.KMXFile.CODE_CONTEXTEX: // I3980 Result += `k.KCCM(${Len-Cur},${Len-rec.ContextEx.Index+1},t)`; break; - case KMXFile.CODE_NOTANY: // I3981 - CheckStoreForInvalidFunctions(fkp, rec.Any.Store); // I1520 + case KMX.KMXFile.CODE_NOTANY: // I3981 + CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520 Result += `k.KC(${Len-Cur},1,t)!=""&&!k.KA(${Cur},k.KC(${Len-Cur},1,t),`+ `this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)})`; break; @@ -410,7 +851,7 @@ function JavaScript_CompositeContextValue(fk: KEYBOARD, fkp: KEY, pwsz: string): if(rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0)) { Result += '\\'; } - Result += Javascript_String(rec.ChrVal); // I2242 + Result += JavaScript_String(rec.ChrVal); // I2242 } Cur++; @@ -424,7 +865,7 @@ function JavaScript_CompositeContextValue(fk: KEYBOARD, fkp: KEY, pwsz: string): } // Used when targeting versions >= 10.0, after the introduction of FullContextMatch/KFCM. -function JavaScript_FullContextValue(fk: KEYBOARD, fkp: KEY, pwsz: string): string { +function JavaScript_FullContextValue(fk: KMX.KEYBOARD, fkp: KMX.KEY, pwsz: string): string { /*var Len: Integer; rec: TSentinelRecord; @@ -444,17 +885,17 @@ begin*/ let rec = ExpandSentinel(fk, pwsz, x); if(rec.IsSentinel) { switch(rec.Code) { - case KMXFile.CODE_ANY: - CheckStoreForInvalidFunctions(fkp, rec.Any.Store); // I1520 + case KMX.KMXFile.CODE_ANY: + CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520 FullContext += `{t:'a',a:this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)}}`; break; - case KMXFile.CODE_DEADKEY: + case KMX.KMXFile.CODE_DEADKEY: FullContext += `{t:'d',d:${rec.DeadKey.DeadKey}}`; break; - case KMXFile.CODE_NUL: // I2243 + case KMX.KMXFile.CODE_NUL: // I2243 FullContext += `{t:'n'}`; break; - case KMXFile.CODE_IFOPT: // I3429 + case KMX.KMXFile.CODE_IFOPT: // I3429 Len--; if(Suffix != '') { Suffix += '&&'; @@ -465,7 +906,7 @@ begin*/ Suffix += `this.s${JavaScript_Name(rec.IfOpt.StoreIndex1, rec.IfOpt.Store1.dpName)}`+ `${rec.IfOpt.IsNot == 0 ? '!==' : '==='}this.s${JavaScript_Name(rec.IfOpt.StoreIndex2,rec.IfOpt.Store2.dpName)}`; // I3429 // I3659 // I3681 break; - case KMXFile.CODE_IFSYSTEMSTORE: // I3430 + case KMX.KMXFile.CODE_IFSYSTEMSTORE: // I3430 Len--; if(Suffix != '') { Suffix += '&&'; @@ -476,19 +917,19 @@ begin*/ Suffix += `${rec.IfSystemStore.IsNot == 0 ? '!' : ''}k.KIFS(${rec.IfSystemStore.dwSystemID},`+ `this.s${JavaScript_Name(rec.IfSystemStore.StoreIndex,rec.IfSystemStore.Store.dpName)},t)`; // I3430 // I3659 // I3681 break; - case KMXFile.CODE_NOTANY: // I3981 - CheckStoreForInvalidFunctions(fkp, rec.Any.Store); // I1520 + case KMX.KMXFile.CODE_NOTANY: // I3981 + CheckStoreForInvalidFunctions(fk, fkp, rec.Any.Store); // I1520 FullContext += `{t:'a',a:this.s${JavaScript_Name(rec.Any.StoreIndex, rec.Any.Store.dpName)},n:1}`; break; - case KMXFile.CODE_CONTEXTEX: + case KMX.KMXFile.CODE_CONTEXTEX: FullContext += `{t:'c',c:${rec.ContextEx.Index}}`; // I4611 break; - case KMXFile.CODE_INDEX: - FullContext += `{t:'i',i:this.s${JavaScript_Name(rec.Index.StoreIndex, rec.Index.Store.szName)},`+ + case KMX.KMXFile.CODE_INDEX: + FullContext += `{t:'i',i:this.s${JavaScript_Name(rec.Index.StoreIndex, rec.Index.Store.dpName)},`+ `o:${rec.Index.Index}}`; // I4611 break; default: - ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, `Statement ${GetCodeName(rec.Code)} is not currently supported in context`; // I1971 // I4061 + ReportError(fkp.Line, CERR_NotSupportedInKeymanWebContext, `Statement ${GetCodeName(rec.Code)} is not currently supported in context`); // I1971 // I4061 Result += '/*.*/ 0 '; } } @@ -498,7 +939,7 @@ begin*/ if(rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0) || rec.ChrVal == '\''.charCodeAt(0)) { FullContext += '\\'; } - FullContext += Javascript_String(rec.ChrVal) + `'`; // I2242 + FullContext += JavaScript_String(rec.ChrVal) + `'`; // I2242 } x = incxstr(pwsz, x); @@ -517,7 +958,18 @@ begin*/ return Result; } -export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KEY, pwszOutput: string, fgp: GROUP): string { +function isGroupReadOnly(fk: KMX.KEYBOARD, fgp: KMX.GROUP) { + // TODO: export group + store metadata in debug store, use that + return false; +} + +function CallFunctionName(s: string): string { + let n: number; + n = s.indexOf(':'); + return s.substring(n+1); // not found gives -1, substring(0) is ok :grin: +} + +export function JavaScript_OutputString(fk: KMX.KEYBOARD, FTabStops: string, fkp: KMX.KEY, pwszOutput: string, fgp: KMX.GROUP): string { let InQuotes = false; let len = 0; const nlt = nl + FTabStops; // I3681 @@ -537,18 +989,18 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE let recContext = ExpandSentinel(fk, pwszContext, x); if(IsKeyboardVersion10OrLater()) { - if(recContext.IsSentinel && [KMXFile.CODE_NUL, KMXFile.CODE_IFOPT, KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) { + if(recContext.IsSentinel && [KMX.KMXFile.CODE_NUL, KMX.KMXFile.CODE_IFOPT, KMX.KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) { Result--; } } else { - if(recContext.IsSentinel && [KMXFile.CODE_DEADKEY, KMXFile.CODE_NUL,KMXFile. KMXFile.CODE_IFOPT, KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) { + if(recContext.IsSentinel && [KMX.KMXFile.CODE_DEADKEY, KMX.KMXFile.CODE_NUL, KMX.KMXFile.CODE_IFOPT, KMX.KMXFile.CODE_IFSYSTEMSTORE].includes(recContext.Code)) { Result--; } } x = incxstr(pwszContext, x); } - return Result; + return Result + 1; // 1-based } const ContextChar = function(ContextIndex: number, pwszContext: string, xContext: number): string { // I4611 @@ -562,14 +1014,14 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE } switch(recContext.Code) { - case KMXFile.CODE_ANY: + case KMX.KMXFile.CODE_ANY: Index = AdjustIndex(fkp.dpContext, ContextIndex); // I3910 // I4611 Result += nlt + `k.KIO(${len},this.s${JavaScript_Name(recContext.Any.StoreIndex, recContext.Any.Store.dpName)},${Index},t);`; // I4611 break; - case KMXFile.CODE_DEADKEY: + case KMX.KMXFile.CODE_DEADKEY: Result += nlt + `k.KDO(${len},t,${recContext.DeadKey.DeadKey});`; // I4611 break; - case KMXFile.CODE_NOTANY: + case KMX.KMXFile.CODE_NOTANY: // #917: Minimum version required is 14.0: the KCXO function was only added for 14.0 // Note that this is checked in compiler.cpp as well, so this error can probably never occur if(!IsKeyboardVersion14OrLater()) { @@ -577,9 +1029,9 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE } Result += nlt + `k.KCXO(${len},t,${AdjustIndex(fkp.dpContext, xstrlen(fkp.dpContext))},${AdjustIndex(fkp.dpContext, ContextIndex)});`; break; - case KMXFile.CODE_IFOPT: - case KMXFile.CODE_IFSYSTEMSTORE: - case KMXFile.CODE_NUL: + case KMX.KMXFile.CODE_IFOPT: + case KMX.KMXFile.CODE_IFSYSTEMSTORE: + case KMX.KMXFile.CODE_NUL: // These have no output for a context emit break; default: @@ -610,12 +1062,12 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE if(IsKeyboardVersion10OrLater()) { // KMW >= 10.0 use the full, sentinel-based length for context deletions. len = xstrlen(fkp.dpContext); - n = len; + let n = len; let x = 0; for(let i = 0; i < n; i++) { let rec = ExpandSentinel(fk, fkp.dpContext, x); - if(rec.IsSentinel && [KMXFile.CODE_NUL, KMXFile.CODE_IFOPT, KMXFile.CODE_IFSYSTEMSTORE].includes(rec.Code)) { + if(rec.IsSentinel && [KMX.KMXFile.CODE_NUL, KMX.KMXFile.CODE_IFOPT, KMX.KMXFile.CODE_IFSYSTEMSTORE].includes(rec.Code)) { len--; } x = incxstr(fkp.dpContext, x); @@ -633,7 +1085,7 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE let x = 0; if(IsKeyboardVersion10OrLater() && pwsz.length > 0) { - if(fgp.fReadOnly) { + if(!isGroupReadOnly(fk, fgp)) { Result += nlt+`k.KDC(${len},t);`; // I3681 } len = -1; @@ -643,19 +1095,19 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE let rec = ExpandSentinel(fk, pwsz, x); if(rec.IsSentinel) { if(InQuotes) { - if(!fgp.fReadOnly) { + if(!isGroupReadOnly(fk, fgp)) { Result += '");'; } InQuotes = false; } switch(rec.Code) { - case KMXFile.CODE_CONTEXT: + case KMX.KMXFile.CODE_CONTEXT: if (x > 0 || len == -1) { let xContext = 0; - n = 1; + let n = 0; while(xContext < fkp.dpContext.length) { // I4611 - if(!fgp.fReadOnly) { + if(!isGroupReadOnly(fk, fgp)) { Result += ContextChar(n, fkp.dpContext, xContext); } n++; @@ -666,19 +1118,19 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE // else, we don't need to output anything - just don't delete the context len = -1; break; - case KMXFile.CODE_CONTEXTEX: + case KMX.KMXFile.CODE_CONTEXTEX: let xContext = 0; for(let i = 0; i < rec.ContextEx.Index; i++) { xContext = incxstr(fkp.dpContext, xContext); } - if(!fgp.fReadOnly) { + if(!isGroupReadOnly(fk, fgp)) { Result += ContextChar(rec.ContextEx.Index, fkp.dpContext, xContext); // I4611 } len = -1; break; - case KMXFile.CODE_BEEP: - if(!fgp.fReadOnly) { + case KMX.KMXFile.CODE_BEEP: + if(!isGroupReadOnly(fk, fgp)) { if(len > 0) { Result += nlt+`k.KO(${len},t,"");`; // I3681 } @@ -686,16 +1138,16 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE } len = -1; break; - case KMXFile.CODE_NUL: - if(!fgp.fReadOnly) { + case KMX.KMXFile.CODE_NUL: + if(!isGroupReadOnly(fk, fgp)) { if(len > 0) { Result += nlt+`k.KO(${len},t,"");`; // I3681 } } len = -1; break; - case KMXFile.CODE_INDEX: - CheckStoreForInvalidFunctions(fkp, rec.Index.Store); // I1520 + case KMX.KMXFile.CODE_INDEX: + CheckStoreForInvalidFunctions(fk, fkp, rec.Index.Store); // I1520 // This code was wrong. We need to ignore CODE_NUL, CODE_DEADKEY in LHS context index counter. // This is why the compiler goes wrong -- and why the previous fix was inconsistent. @@ -705,7 +1157,7 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE let Index = AdjustIndex(fkp.dpContext, rec.Index.Index); // I3910 - if(!fgp.fReadOnly) { + if(!isGroupReadOnly(fk, fgp)) { Result += nlt+`k.KIO(${len},this.s${JavaScript_Name(rec.Index.StoreIndex, rec.Index.Store.dpName)},${Index},t);`; // I783 - was: rec.Index.Index [2007-06-04] // I783 again. Returned to rec.Index.Index. Was previously: [2008-08-15] @@ -716,14 +1168,14 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE } len = -1; break; - case KMXFile.CODE_DEADKEY: - if(!fgp.fReadOnly) { + case KMX.KMXFile.CODE_DEADKEY: + if(!isGroupReadOnly(fk, fgp)) { Result += nlt+`k.KDO(${len},t,${rec.DeadKey.DeadKey});`; // I3681 } len = -1; break; - case KMXFile.CODE_USE: - if(!fgp.fReadOnly) { + case KMX.KMXFile.CODE_USE: + if(!isGroupReadOnly(fk, fgp)) { if(len > 0) { Result += nlt+`k.KO(${len},t,"");`; // I3681 } @@ -732,22 +1184,22 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE Result += nlt+'m=2;'; // #5440 - match desktop behavior len = -1; break; - case KMXFile.CODE_CALL: - if(!fgp.fReadOnly) { + case KMX.KMXFile.CODE_CALL: + if(!isGroupReadOnly(fk, fgp)) { if(len > 0) { Result += nlt+`k.KO(${len},t,"");`; // I3681 } } - n = FCallFunctions.IndexOf(CallFunctionName(rec.Call.Store.dpString)); + let n = FCallFunctions.indexOf(CallFunctionName(rec.Call.Store.dpString)); if(n == -1) { - n = FCallFunctions.Add(CallFunctionName(rec.Call.Store.dpString)); + n = FCallFunctions.push(CallFunctionName(rec.Call.Store.dpString)); } Result += nlt+`r=this.c${n}(t,e);`; // I1959 // I3681 Result += nlt+'m=2;'; // #5440 - match desktop behavior len = -1; break; - case KMXFile.CODE_SETOPT: // I3429 - if(!fgp.fReadOnly) { + case KMX.KMXFile.CODE_SETOPT: // I3429 + if(!isGroupReadOnly(fk, fgp)) { if(len > 0) { Result += nlt+`k.KO(${len},t,"");`; // I3681 } @@ -756,8 +1208,8 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE `this.s${JavaScript_Name(rec.SetOpt.StoreIndex2,rec.SetOpt.Store2.dpName)};`; len = -1; break; - case KMXFile.CODE_RESETOPT: // I3429 - if(!fgp.fReadOnly) { + case KMX.KMXFile.CODE_RESETOPT: // I3429 + if(!isGroupReadOnly(fk, fgp)) { if(len > 0) { Result += nlt+`k.KO(${len},t,"");`; // I3681 } @@ -765,11 +1217,11 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE Result += nlt+`this.s${JavaScript_Name(rec.ResetOpt.StoreIndex,rec.ResetOpt.Store.dpName)}=`+ `k.KLOAD(this.KI,"${JavaScript_Name(rec.ResetOpt.StoreIndex,rec.ResetOpt.Store.dpName,true)}",`+ - `${JavaScript_Store(fkp.Line, rec.ResetOpt.Store.dpString)});`; // I3429 // I3681 // I3659 + `${JavaScript_Store(fk, fkp.Line, rec.ResetOpt.Store.dpString)});`; // I3429 // I3681 // I3659 len = -1; break; - case KMXFile.CODE_SAVEOPT: // I3429 - if(!fgp.fReadOnly) { + case KMX.KMXFile.CODE_SAVEOPT: // I3429 + if(!isGroupReadOnly(fk, fgp)) { if(len > 0) { Result += nlt+`k.KO(${len},t,"");`; // I3681 } @@ -779,8 +1231,8 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE `this.s${JavaScript_Name(rec.SaveOpt.StoreIndex,rec.SaveOpt.Store.dpName)});`; // I3690 // I3429 // I3659 // I3681 len = -1; break; - case KMXFile.CODE_SETSYSTEMSTORE: // I3437 - if(!fgp.fReadOnly) { + case KMX.KMXFile.CODE_SETSYSTEMSTORE: // I3437 + if(!isGroupReadOnly(fk, fgp)) { if(len > 0) { Result += nlt+`k.KO(${len},t,"");`; // I3681 } @@ -797,15 +1249,13 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE } else { if(!InQuotes) { - if(!fgp.fReadOnly) { - if(len > 0) { - Result += nlt+`k.KO(${len},t,"");`; // I3681 - } + if(!isGroupReadOnly(fk, fgp)) { + Result += nlt+`k.KO(${len},t,"`; // I3681 } InQuotes = true; len = -1; } - if(!fgp.fReadOnly) { + if(!isGroupReadOnly(fk, fgp)) { if(rec.ChrVal == '"'.charCodeAt(0) || rec.ChrVal == '\\'.charCodeAt(0)) { Result += '\\'; } @@ -817,20 +1267,285 @@ export function JavaScript_OutputString(fk: KEYBOARD, FTabStops: string, fkp: KE } if(InQuotes) { - if(!fgp.fReadOnly) { + if(!isGroupReadOnly(fk, fgp)) { Result += '");'; } } return Result; } -function zeroPadHex(n: number, len: number): string { - let result = n.toString(16); +export function zeroPadHex(n: number, len: number): string { + let result = n.toString(16).toUpperCase(); if(result.length < len) { - return + return '0'.repeat(len - result.length) + result; } + return result; } +// TODO: move elsewhere +/// +/// Virtual key names used in KeymanWeb. Blanks indicate a +/// virtual key that is not recognised by KeymanWeb. +/// +const KMWVKeyNames: string[] = [ + '', + '', + '', + '', + '', + '', + '', + '', + 'K_BKSP', + 'K_TAB', + '', + '', + '', + 'K_ENTER', + '', + '', + 'K_SHIFT', + 'K_CONTROL', + 'K_ALT', + 'K_PAUSE', + 'K_CAPS', + '', + '', + '', + '', + '', + '', + 'K_ESC', + '', + '', + '', + '', + 'K_SPACE', + 'K_PGUP', + 'K_PGDN', + 'K_END', + 'K_HOME', + 'K_LEFT', + 'K_UP', + 'K_RIGHT', + 'K_DOWN', + 'K_SEL', + 'K_PRINT', + 'K_EXEC', + '', + 'K_INS', + 'K_DEL', + 'K_HELP', + 'K_0', + 'K_1', + 'K_2', + 'K_3', + 'K_4', + 'K_5', + 'K_6', + 'K_7', + 'K_8', + 'K_9', + '', + '', + '', + '', + '', + '', + '', + 'K_A', + 'K_B', + 'K_C', + 'K_D', + 'K_E', + 'K_F', + 'K_G', + 'K_H', + 'K_I', + 'K_J', + 'K_K', + 'K_L', + 'K_M', + 'K_N', + 'K_O', + 'K_P', + 'K_Q', + 'K_R', + 'K_S', + 'K_T', + 'K_U', + 'K_V', + 'K_W', + 'K_X', + 'K_Y', + 'K_Z', + '', + '', + '', + '', + '', + 'K_NP0', + 'K_NP1', + 'K_NP2', + 'K_NP3', + 'K_NP4', + 'K_NP5', + 'K_NP6', + 'K_NP7', + 'K_NP8', + 'K_NP9', + 'K_NPSTAR', + 'K_NPPLUS', + 'K_SEPARATOR', + 'K_NPMINUS', + 'K_NPDOT', + 'K_NPSLASH', + 'K_F1', + 'K_F2', + 'K_F3', + 'K_F4', + 'K_F5', + 'K_F6', + 'K_F7', + 'K_F8', + 'K_F9', + 'K_F10', + 'K_F11', + 'K_F12', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'K_NUMLOCK', + 'K_SCROLL', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'K_LSHIFT', + 'K_RSHIFT', + 'K_LCONTROL', + 'K_RCONTROL', + 'K_LALT', + 'K_RALT', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'K_COLON', + 'K_EQUAL', + 'K_COMMA', + 'K_HYPHEN', + 'K_PERIOD', + 'K_SLASH', + 'K_BKQUOTE', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + 'K_LBRKT', + 'K_BKSLASH', + 'K_RBRKT', + 'K_QUOTE', + '', + '', + '', + 'K_oE2', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '', + '' +]; + /** * Converts a key value into a constant * @@ -842,9 +1557,9 @@ function FormatKeyAsString(key: number): string { if(IsKeyboardVersion10OrLater()) { // Depends on flags defined in KeymanWeb 10.0 if (key <= 255 && KMWVKeyNames[key] != '') { - Result = 'keyCodes.'+KMWVKeyNames[key]+ ' /* 0x' + zeroPadHex(key, 2) + ' */' - else Result := '0x' + IntToHex(key, 2); - end - else - Result := '0x' + IntToHex(key, 2); -end; + return 'keyCodes.'+KMWVKeyNames[key]+ ' /* 0x' + zeroPadHex(key, 2) + ' */'; + } + return '0x' + zeroPadHex(key, 2); + } + return '0x' + zeroPadHex(key, 2); +} diff --git a/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts b/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts deleted file mode 100644 index 1b162b738a..0000000000 --- a/developer/src/kmc-kmw/src/compiler/keymanweb-compiler.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { VisualKeyboard } from "@keymanapp/common-types"; -import * as path from 'path'; - -import { KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; -// import VisualKeyboardCompiler from "./visual-keyboard-compiler.js"; -import { nl, FTabStop, setupGlobals } from "./compiler-globals.js"; -import CompilerOptions from "./compiler-options.js"; - -export class KeymanWebCompiler { - private readonly options: CompilerOptions; - private readonly nl: string; - private readonly tab: string; - - constructor(options?: CompilerOptions) { - this.options = options; - this.nl = this.options.debug ? "\n" : ''; - this.tab = this.options.debug ? " " : ''; - setupGlobals(this.options, this.tab, this.nl); - } - - public compile(name: string, source: KMXFile): string { - const nl = this.nl, tab = this.tab; - - // TODO: fill in from CompileKeymanWeb.pas - - const sName = 'Keyboard_'+this.cleanName(name); - const displayUnderlying = true; // TODO-LDML - const modifierBitmask = 0; // TODO-LDML: define the modifiers used by this keyboard - const vkDictionary = ''; // TODO-LDML: vk dictionary for touch keys - const hasSupplementaryPlaneChars = false; // TODO-LDML - const isRTL = false; // TODO-LDML - - let result = - `if(typeof keyman === 'undefined') {${nl}` + - `${tab}console.error('Keyboard requires KeymanWeb ${MINIMUM_KMW_VERSION} or later');${nl}` + - `} else {${nl}` + - `${tab}KeymanWeb.KR(new ${sName}());${nl}` + - `}${nl}` + - `function ${sName}() {${nl}` + - // `${tab}${this.setupDebug()}${nl}` + ? we may use this for modifierBitmask in future - // `${tab}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` + ? we probably don't need this, it's for back-compat - `${tab}this.KI="${sName}";${nl}` + - `${tab}this.KN=${JSON.stringify(source.keyboard.names.name[0])};${nl}` + - `${tab}this.KMINVER=${JSON.stringify(MINIMUM_KMW_VERSION)};${nl}` + - `${tab}this.KV=${this.compileVisualKeyboard(source)};${nl}` + - `${tab}this.KDU=${displayUnderlying ? '1' : '0'};${nl}` + - `${tab}this.KH="";${nl}` + // TODO-LDML: help text not supported - `${tab}this.KM=0;${nl}` + // TODO-LDML: mnemonic layout not supported for LDML keyboards - `${tab}this.KBVER=${JSON.stringify(source.keyboard.version.number)};${nl}` + - `${tab}this.KMBM=${modifierBitmask};${nl}`; - - if(isRTL) { - result += `${tab}this.KRTL=1;${nl}`; - } - - if(hasSupplementaryPlaneChars) { - result += `${tab}this.KS=1;${nl}`; - } - - if(vkDictionary != '') { - result += `${tab}this.KVKD=${JSON.stringify(vkDictionary)};${nl}`; - } - - let layoutFile = this.compileTouchLayout(source); - if(layoutFile != '') { - result += `${tab}this.KVKL=${layoutFile};${nl}`; - } - // TODO-LDML: KCSS not supported - - // TODO-LDML: embed binary keyboard for loading into Core - - // A LDML keyboard has a no-op for its gs() (begin Unicode) function, - // because the functionality is embedded in Keyman Core - result += `${tab}this.gs=function(t,e){${nl}`+ - `${tab}${tab}return 0;${nl}`+ // TODO-LDML: we will start by embedding call into Keyman Core here - `${tab}};${nl}`; - - result += `}${nl}`; - return result; - } -} \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/messages.ts b/developer/src/kmc-kmw/src/compiler/messages.ts index 9f443cfc0d..07bd2794ca 100644 --- a/developer/src/kmc-kmw/src/compiler/messages.ts +++ b/developer/src/kmc-kmw/src/compiler/messages.ts @@ -1,4 +1,4 @@ -import { FCompilerWarningsAsErrors } from "./compiler-globals.js"; +import { callbacks, FCompilerWarningsAsErrors } from "./compiler-globals.js"; export let FError = false; @@ -10,7 +10,8 @@ export function ReportError(line: number, msgcode: number, text: string) { // I if (msgcode & flag) { FError = true; } - FCallback(line, msgcode, text); // I3310 + // TODO: these Codes Are All Wrong But We'll Fix It Soon + callbacks.reportMessage({code: msgcode, message: text, line}); // I3310 } export const diff --git a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts index b065a1ea0f..0175072aeb 100644 --- a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts +++ b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts @@ -1,8 +1,9 @@ -import { ExpandSentinel, incxstr, xstrlen } from "src/util/util.js"; -import { GROUP, KEY, KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx.js"; +import { KMX, CompilerCallbacks } from "@keymanapp/common-types"; +import { ExpandSentinel, incxstr, xstrlen } from "../util/util.js"; +// import { KEY, KEYBOARD, KMX.KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx.js"; import { options, nl, FTabStop, setupGlobals, IsKeyboardVersion10OrLater } from "./compiler-globals.js"; import CompilerOptions from "./compiler-options.js"; -import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaScript_OutputString, JavaScript_Rules, JavaScript_Shift, JavaScript_ShiftAsString, JavaScript_Store } from './javascript-strings.js'; +import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaScript_OutputString, JavaScript_Rules, JavaScript_Shift, JavaScript_ShiftAsString, JavaScript_Store, zeroPadHex } from './javascript-strings.js'; import { CERR_InvalidBegin, CWARN_DontMixChiralAndNonChiralModifiers, ReportError } from "./messages.js"; export let FFix183_LadderLength: number = 100; // TODO: option @@ -29,33 +30,34 @@ function RequotedString(s: string, RequoteSingleQuotes: boolean = false): string else if(s.charAt(i) == '\r') { s = s.substring(0, i) + ' ' + s.substring(i + 1); } + i++; } return s; } -export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boolean = false): string { +export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, name: string, keyboard: KMX.KEYBOARD, FDebug: boolean = false): string { let opts: CompilerOptions = { addCompilerVersion: false, debug: FDebug }; - setupGlobals(opts, FDebug?' ':'', FDebug?'\n':'', source.keyboard); + setupGlobals(callbacks, opts, FDebug?' ':'', FDebug?'\n':'', keyboard); // let fgp: GROUP; - let fsp: STORE; - let fkp: KEY; + // let fsp: STORE; + // let fkp: KEY; - let j: number; - let n: number; + // let j: number; + // let n: number; let vMnemonic: number = 0; - let s: string, sRTL: string = "", sHelp: string = "''", sHelpFile: string = "", + let /*s: string,*/ sRTL: string = "", sHelp: string = "''", sHelpFile: string = "", sEmbedJS: string = "", sEmbedCSS: string = ""; let sVisualKeyboard: string = "", sFullName: string = ""; - let sBegin_NewContext: string, sBegin_PostKeystroke: string; + let sBegin_NewContext: string = "", sBegin_PostKeystroke: string = ""; let sLayoutFile: string = "", sVKDictionary: string; let linecomment: string; // I3438 - let HasRules: boolean; + // let HasRules: boolean; let sModifierBitmask: string; let FOptionStores: string; let FKeyboardVersion = "1.0"; @@ -63,45 +65,45 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo let result = ""; // Locate the name of the keyboard - for(let i = 0; i < source.keyboard.stores.length; i++) { - const fsp = source.keyboard.stores[i]; - if(fsp.dwSystemID == KMXFile.TSS_NAME) { + for(let i = 0; i < keyboard.stores.length; i++) { + const fsp = keyboard.stores[i]; + if(fsp.dwSystemID == KMX.KMXFile.TSS_NAME) { sFullName = fsp.dpString; } - else if(fsp.dwSystemID == KMXFile.TSS_KEYBOARDVERSION) { // I4155 + else if(fsp.dwSystemID == KMX.KMXFile.TSS_KEYBOARDVERSION) { // I4155 FKeyboardVersion = fsp.dpString; } - else if (fsp.dpName == 'HelpFile' || fsp.dwSystemID == KMXFile.TSS_KMW_HELPFILE) { + else if (fsp.dpName == 'HelpFile' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_HELPFILE) { sHelpFile = fsp.dpString; } - else if (fsp.dpName == 'Help' || fsp.dwSystemID == KMXFile.TSS_KMW_HELPTEXT) { + else if (fsp.dpName == 'Help' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_HELPTEXT) { sHelp = '"'+RequotedString(fsp.dpString)+'"'; } - else if (fsp.dpName == 'VisualKeyboard' || fsp.dwSystemID == KMXFile.TSS_VISUALKEYBOARD) { + else if (fsp.dpName == 'VisualKeyboard' || fsp.dwSystemID == KMX.KMXFile.TSS_VISUALKEYBOARD) { sVisualKeyboard = fsp.dpString; } - else if (fsp.dpName == 'EmbedJS' || fsp.dwSystemID == KMXFile.TSS_KMW_EMBEDJS) { + else if (fsp.dpName == 'EmbedJS' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_EMBEDJS) { sEmbedJS = fsp.dpString; } - else if (fsp.dpName == 'EmbedCSS' || fsp.dwSystemID == KMXFile.TSS_KMW_EMBEDCSS) { // I4368 + else if (fsp.dpName == 'EmbedCSS' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_EMBEDCSS) { // I4368 sEmbedCSS = fsp.dpString; } - else if (fsp.dpName == 'RTL' || fsp.dwSystemID == KMXFile.TSS_KMW_RTL) { + else if (fsp.dpName == 'RTL' || fsp.dwSystemID == KMX.KMXFile.TSS_KMW_RTL) { sRTL = fsp.dpString == '1' ? FTabStop+'this.KRTL=1;'+nl : ''; // I3681 } - else if (fsp.dwSystemID == KMXFile.TSS_MNEMONIC) { + else if (fsp.dwSystemID == KMX.KMXFile.TSS_MNEMONIC) { vMnemonic = fsp.dpString == '1' ? 1 : 0; } - else if (fsp.dwSystemID == KMXFile.TSS_VKDICTIONARY) { // I3438 + else if (fsp.dwSystemID == KMX.KMXFile.TSS_VKDICTIONARY) { // I3438 sVKDictionary = fsp.dpString; } - else if (fsp.dwSystemID == KMXFile.TSS_LAYOUTFILE) { // I3483 + else if (fsp.dwSystemID == KMX.KMXFile.TSS_LAYOUTFILE) { // I3483 sLayoutFile = fsp.dpString; } - else if (fsp.dwSystemID == KMXFile.TSS_BEGIN_NEWCONTEXT) { + else if (fsp.dwSystemID == KMX.KMXFile.TSS_BEGIN_NEWCONTEXT) { sBegin_NewContext = fsp.dpString; } - else if (fsp.dwSystemID -= KMXFile.TSS_BEGIN_POSTKEYSTROKE) { + else if (fsp.dwSystemID == KMX.KMXFile.TSS_BEGIN_POSTKEYSTROKE) { sBegin_PostKeystroke = fsp.dpString; } } @@ -219,22 +221,23 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo sVisualKeyboard = 'null'; } - sModifierBitmask = GetKeyboardModifierBitmask(source); const fMnemonic = vMnemonic == 1; + sModifierBitmask = GetKeyboardModifierBitmask(keyboard, fMnemonic); + result += - `${JavaScript_SetupProlog}${nl}` + - `'KeymanWeb.KR(new ${sName}());${nl}` + - `${JavaScript_SetupEpilog}${nl}` + + `${JavaScript_SetupProlog()}${nl}` + + `KeymanWeb.KR(new ${sName}());${nl}` + + `${JavaScript_SetupEpilog()}${nl}` + `function ${sName}()${nl}` + `{${nl}` + - `${FTabStop}${JavaScript_SetupDebug}${nl}` + + `${FTabStop}${JavaScript_SetupDebug()}${nl}` + // Following line caches the Keyman major version `${FTabStop}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` + `${FTabStop}this.KI="${sName}";${nl}` + `${FTabStop}this.KN="${RequotedString(sFullName)}";${nl}`, nl, - `${FTabStop}this.KMINVER="${(source.keyboard.fileVersion & KMXFile.VERSION_MASK_MAJOR) >> 8}.${source.keyboard.fileVersion & KMXFile.VERSION_MASK_MINOR}";${nl}` + + `${FTabStop}this.KMINVER="${(keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MAJOR) >> 8}.${keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MINOR}";${nl}` + `${FTabStop}this.KV=${sVisualKeyboard};${nl}` + `${FTabStop}this.KDU=${fDisplayUnderlying?'1':'0'};${nl}` + `${FTabStop}this.KH=${sHelp};${nl}` + @@ -259,45 +262,45 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo result += `${FTabStop}this.KCSS="${RequotedString(sEmbedCSS)}";${nl}`; } - function isDebugStore(fsp: STORE) { - return fsp.dwSystemID == KMXFile.TSS_DEBUG_LINE; + function isDebugStore(fsp: KMX.STORE) { + return fsp.dwSystemID == KMX.KMXFile.TSS_DEBUG_LINE; } - function isReservedStore(fsp: STORE) { - return fsp.dwSystemID != KMXFile.TSS_NONE; + function isReservedStore(fsp: KMX.STORE) { + return fsp.dwSystemID != KMX.KMXFile.TSS_NONE; } - function isOptionStore(fsp: STORE) { + function isOptionStore(fsp: KMX.STORE) { // TODO: how do we determine this, see CheckStoreUsage() return false; } // Write the stores out FOptionStores = ''; - for(let i = 0; i < source.keyboard.stores.length; i++) { - let fsp = source.keyboard.stores[i]; + for(let i = 0; i < keyboard.stores.length; i++) { + let fsp = keyboard.stores[i]; // I3438 - Save all system stores to the keyboard, for now // I3684 if (!isDebugStore(fsp)) { // and not (fsp.dwSystemID in [TSS_BITMAP, TSS_NAME, TSS_VERSION, TSS_CUSTOMKEYMANEDITION, TSS_CUSTOMKEYMANEDITIONNAME, TSS_KEYMANCOPYRIGHT]) then - if (fsp.dwSystemID == KMXFile.TSS_COMPARISON) { - result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(fsp.line, fsp.dpString)};${nl}`; + if (fsp.dwSystemID == KMX.KMXFile.TSS_COMPARISON) { + result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)};${nl}`; } - else if (fsp.dwSystemID == KMXFile.TSS_COMPILEDVERSION) { - result += `${FTabStop}this.KVER=${JavaScript_Store(fsp.line, fsp.dpString)};${nl}`; + else if (fsp.dwSystemID == KMX.KMXFile.TSS_COMPILEDVERSION) { + result += `${FTabStop}this.KVER=${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)};${nl}`; } //else if fsp.dwSystemID = TSS_VKDICTIONARY then // I3438, required for vkdictionary // Result := Result + Format('%sthis.s%s=%s;%s', [FTabStop, JavaScript_Name(i, fsp.szName), JavaScript_Store(fsp.line, fsp.dpString), nl]) else if (isOptionStore(fsp) && !isReservedStore(fsp)) { result += `${FTabStop}this.s${JavaScript_Name(i,fsp.dpName)}=KeymanWeb.KLOAD(this.KI,"${JavaScript_Name(i,fsp.dpName,true)}",`+ - `${JavaScript_Store(fsp.line, fsp.dpString)});${nl}`; + `${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)});${nl}`; if (FOptionStores != '') { FOptionStores += ','; } FOptionStores += `'s${JavaScript_Name(i, fsp.dpName)}`; } - else if (fsp.dwSystemID == KMXFile.TSS_NONE /* aka not fsp.fIsReserved */) { - result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(fsp.line, fsp.dpString)};${nl}`; // I3681 + else if (fsp.dwSystemID == KMX.KMXFile.TSS_NONE /* aka not fsp.fIsReserved */) { + result += `${FTabStop}this.s${JavaScript_Name(i, fsp.dpName)}=${JavaScript_Store(keyboard, 0/*fsp.line*/, fsp.dpString)};${nl}`; // I3681 } } } @@ -307,30 +310,30 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo // Write the groups out // I853 - begin unicode missing causes crash - if (source.keyboard.startGroup.unicode == 0xFFFFFFFF) { + if (keyboard.startGroup.unicode == 0xFFFFFFFF) { ReportError(0, CERR_InvalidBegin, 'A "begin unicode" statement is required to compile a KeymanWeb keyboard'); return null; } - result += WriteBeginStatement(source, 'gs', source.keyboard.startGroup.unicode); + result += WriteBeginStatement(keyboard, 'gs', keyboard.startGroup.unicode); - let rec = ExpandSentinel(source.keyboard, sBegin_NewContext, 0); - if(rec.Code == KMXFile.CODE_USE) { - result += WriteBeginStatement(source, 'gn', rec.Use.GroupIndex); + let rec = ExpandSentinel(keyboard, sBegin_NewContext, 0); + if(rec.Code == KMX.KMXFile.CODE_USE) { + result += WriteBeginStatement(keyboard, 'gn', rec.Use.GroupIndex); } - rec = ExpandSentinel(source.keyboard, sBegin_PostKeystroke, 0); - if(rec.Code == KMXFile.CODE_USE) { - result += WriteBeginStatement(source, 'gpk', rec.Use.GroupIndex); + rec = ExpandSentinel(keyboard, sBegin_PostKeystroke, 0); + if(rec.Code == KMX.KMXFile.CODE_USE) { + result += WriteBeginStatement(keyboard, 'gpk', rec.Use.GroupIndex); } - let fgp = source.keyboard.groups[source.keyboard.startGroup.unicode]; + let fgp = keyboard.groups[keyboard.startGroup.unicode]; result += `${FTabStop}this.gs=function(t,e) {${nl}` + - `${FTabStop+FTabStop}return this.g${JavaScript_Name(source.keyboard.startGroup.unicode, fgp.dpName)}(t,e);${nl}` + - `${FTabStop}}${nl}`; // I3681 + `${FTabStop+FTabStop}return this.g${JavaScript_Name(keyboard.startGroup.unicode, fgp.dpName)}(t,e);${nl}` + + `${FTabStop}};${nl}`; // I3681 - for(let i = 0; i < source.keyboard.groups.length; i++) { // I1964 - let fgp = source.keyboard.groups[i]; + for(let i = 0; i < keyboard.groups.length; i++) { // I1964 + let fgp = keyboard.groups[i]; /* Note on `r` and `m` variables in a group function: @@ -363,12 +366,12 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo let HasRules = false; if (FFix183_LadderLength != 0) { - result += JavaScript_Rules(fgp); + result += JavaScript_Rules(keyboard, fMnemonic, fgp); } else { for (let j = 0; j < fgp.keys.length; j++) { // I1964 let fkp = fgp.keys[j]; - if (!RuleIsExcludedByPlatform(source, fkp)) { + if (!RuleIsExcludedByPlatform(keyboard, fkp)) { result += FTabStop+FTabStop; // I3681 if (HasRules) { result += 'else '; @@ -381,7 +384,7 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo if (xstrlen(fkp.dpContext) > 0) { result += fgp.fUsingKeys ? '&&' : 'if('; - result += JavaScript_ContextMatch(source.keyboard, fkp, fkp.dpContext); + result += JavaScript_ContextMatch(keyboard, fkp, fkp.dpContext); } else if (!fgp.fUsingKeys) { result += 'if(1'; @@ -393,10 +396,10 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo `) {${linecomment}${nl}` + FTabStop+FTabStop+FTabStop; if (fgp.fUsingKeys) { // I1959 - result += 'r=m=1;' + JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 + result += 'r=m=1;' + JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 } else { - result += 'm=1;' + JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 + result += 'm=1;' + JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, fkp, fkp.dpOutput, fgp); // I1959 // I3681 } result += `${nl}${FTabStop}${FTabStop}}${nl}`; // I3681 } @@ -406,28 +409,27 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo if(fgp.dpMatch) { result += `${FTabStop+FTabStop}if(m==1) {${nl}`+ - `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop}${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpMatch, fgp)}${nl}`+ `${FTabStop+FTabStop}}${nl}`; } if(fgp.dpNoMatch) { if(fgp.fUsingKeys) { // I1382 - fixup m=1 to m=g() result += `${FTabStop+FTabStop}if(!m&&k.KIK(e)) {${nl}`+ - `${FTabStop+FTabStop+FTabStop}r=1;${JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop+FTabStop}r=1;${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ `${FTabStop+FTabStop}}${nl}`; // I1959. part 2, I2224 // I3681 } else { result += `${FTabStop+FTabStop}if(!m) {${nl}`+ - `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(source.keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ + `${FTabStop+FTabStop+FTabStop}${JavaScript_OutputString(keyboard, FTabStop + FTabStop + FTabStop, null, fgp.dpNoMatch, fgp)}${nl}`+ `${FTabStop+FTabStop}}${nl}`; } - + } result += `${FTabStop+FTabStop}return r;${nl}`+ - `${FTabStop+FTabStop}};${nl}`; + `${FTabStop}};${nl}`; } -} /* TODO for(let n = 0 to FCallFunctions.Count - 1 do @@ -455,27 +457,27 @@ export function WriteCompiledKeyboard(name: string, source: KMXFile, FDebug: boo /// /// @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 */' /// -function GetKeyboardModifierBitmask(source: KMXFile): string { +function GetKeyboardModifierBitmask(keyboard: KMX.KEYBOARD, fMnemonic: boolean): string { let bitMask = 0; - for(let gp of source.keyboard.groups) { + for(let gp of keyboard.groups) { if(gp.fUsingKeys) { for(let kp of gp.keys) { - if(!RuleIsExcludedByPlatform(source, kp)) { + if(!RuleIsExcludedByPlatform(keyboard, kp)) { bitMask |= JavaScript_Shift(kp, fMnemonic); } } } } - if ((bitMask & KMXFile.KMX_MASK_MODIFIER_CHIRAL) && (bitMask & KMXFile.KMX_MASK_MODIFIER_NONCHIRAL)) { + if ((bitMask & KMX.KMXFile.MASK_MODIFIER_CHIRAL) && (bitMask & KMX.KMXFile.MASK_MODIFIER_NONCHIRAL)) { ReportError(0, CWARN_DontMixChiralAndNonChiralModifiers, 'This keyboard contains Ctrl,Alt and LCtrl,LAlt,RCtrl,RAlt sets of modifiers. Use only one or the other set for web target.'); } if(options.debug) { - return FormatModifierAsBitflags(bitMask & KMXFile.KMX_MASK_KEYS); // Exclude KMX_ISVIRTUALKEY, KMX_VIRTUALCHARKEY + return FormatModifierAsBitflags(bitMask & KMX.KMXFile.MASK_KEYS); // Exclude KMX_ISVIRTUALKEY, KMX_VIRTUALCHARKEY } - return '0x'+(bitMask & KMXFile.KMX_MASK_KEYS).toString(16); + return '0x'+(bitMask & KMX.KMXFile.MASK_KEYS).toString(16).toUpperCase(); } @@ -567,17 +569,17 @@ begin end;*/ } -export function RuleIsExcludedByPlatform(source: KMXFile, fkp: KEY): boolean { +export function RuleIsExcludedByPlatform(keyboard: KMX.KEYBOARD, fkp: KMX.KEY): boolean { if(fkp.dpContext == null || fkp.dpContext == '') { return false; } let x = 0; while(x < fkp.dpContext.length) { - let rec = ExpandSentinel(source.keyboard, fkp.dpContext, x); + let rec = ExpandSentinel(keyboard, fkp.dpContext, x); if(rec.IsSentinel && - (rec.Code == KMXFile.CODE_IFSYSTEMSTORE) && - (rec.IfSystemStore.dwSystemID == KMXFile.TSS_PLATFORM) && + (rec.Code == KMX.KMXFile.CODE_IFSYSTEMSTORE) && + (rec.IfSystemStore.dwSystemID == KMX.KMXFile.TSS_PLATFORM) && rec.IfSystemStore.Store.dpString.includes('native')) { if(rec.IfSystemStore.Store.dpString.match(/windows|desktop|macosx|linux/)) { return true; @@ -589,9 +591,70 @@ export function RuleIsExcludedByPlatform(source: KMXFile, fkp: KEY): boolean { return false; } -function WriteBeginStatement(source: KMXFile, name: string, groupIndex: number): string { - const fgp = source.keyboard.groups[groupIndex]; +function WriteBeginStatement(keyboard: KMX.KEYBOARD, name: string, groupIndex: number): string { + const fgp = keyboard.groups[groupIndex]; return `${FTabStop}this.${name}=function(t,e) {${nl}`+ `${FTabStop+FTabStop}return this.g${JavaScript_Name(groupIndex, fgp.dpName)}(t,e);${nl}`+ `${FTabStop}};${nl}`; -} \ No newline at end of file +} + +/** + * Converts a modifier bit mask integer into its component bit flags + * + * @param FBitMask A KMX modifier bitmask value + * + * @return string of JavaScript code, e.g. 'modCodes.SHIFT | modCodes.CTRL /* 0x0030 ./' +**/ +export function FormatModifierAsBitflags(FBitMask: number): string { + const mask: string[] = [ + 'LCTRL', // 0X0001 + 'RCTRL', // 0X0002 + 'LALT', // 0X0004 + 'RALT', // 0X0008 + + 'SHIFT', // 0X0010 + 'CTRL', // 0X0020 + 'ALT', // 0X0040 + + '???', // Reserved + + 'CAPS', // 0X0100 + 'NO_CAPS', // 0X0200 + + 'NUM_LOCK', // 0X0400 + 'NO_NUM_LOCK', // 0X0800 + + 'SCROLL_LOCK', // 0X1000 + 'NO_SCROLL_LOCK', // 0X2000 + + 'VIRTUAL_KEY' // 0X4000 + ]; + + let i: number; + let result = ''; + + //TODO: We need to think about mnemonic layouts which are incompletely supported at present + //tavultesoft.keymanweb.osk. + + if(IsKeyboardVersion10OrLater()) { + // This depends on flags defined in KeymanWeb 10.0 + result = ''; + + for(i = 0; i < mask.length; i++) { + if(FBitMask & (1 << i)) { + if(result != '') result += ' | '; + result += 'modCodes.'+mask[i]; + } + } + + if(result == '') { + result = '0'; + } + + result += ' /* 0x' + zeroPadHex(FBitMask, 4) + ' */'; + } + else { + result = '0x'+zeroPadHex(FBitMask, 4); + } + return result; +} diff --git a/developer/src/kmc-kmw/src/main.ts b/developer/src/kmc-kmw/src/main.ts index 742b9e4f47..35d6846bce 100644 --- a/developer/src/kmc-kmw/src/main.ts +++ b/developer/src/kmc-kmw/src/main.ts @@ -1,2 +1,2 @@ -export { KeymanWebCompiler } from './compiler/keymanweb-compiler.js'; +export { WriteCompiledKeyboard } from './compiler/write-compiled-keyboard.js'; diff --git a/developer/src/kmc-kmw/src/util/util.ts b/developer/src/kmc-kmw/src/util/util.ts index 1c01a22bf5..21aa9d3c14 100644 --- a/developer/src/kmc-kmw/src/util/util.ts +++ b/developer/src/kmc-kmw/src/util/util.ts @@ -1,4 +1,4 @@ -import { STORE, GROUP, KEYBOARD, KMXFile } from "../../../../../common/web/types/src/kmx/kmx.js"; +import { KMX } from "@keymanapp/common-types"; /** * Verifies that value is an item in the enumeration. @@ -13,11 +13,11 @@ export interface TSentinelRecord { Any?: { StoreIndex: number; - Store: STORE; + Store: KMX.STORE; }; Index?: { StoreIndex: number; - Store: STORE; + Store: KMX.STORE; Index: number; }; DeadKey?: { @@ -25,127 +25,168 @@ export interface TSentinelRecord { }; Use?: { GroupIndex: number; - Group: GROUP; + Group: KMX.GROUP; }; Call?: { StoreIndex: number; - Store: STORE; + Store: KMX.STORE; }; ContextEx?: { Index: number; }; IfOpt?: { StoreIndex1: number; - Store1: STORE; + Store1: KMX.STORE; StoreIndex2: number; - Store2: STORE; + Store2: KMX.STORE; IsNot: number; }; IfSystemStore?: { dwSystemID: number; - SystemStore: STORE; + SystemStore: KMX.STORE; StoreIndex: number; - Store: STORE; + Store: KMX.STORE; IsNot: number; }; SetOpt?: { StoreIndex1: number; - Store1: STORE; + Store1: KMX.STORE; StoreIndex2: number; - Store2: STORE; + Store2: KMX.STORE; }; SetSystemStore?: { dwSystemID: number; - SystemStore: STORE; + SystemStore: KMX.STORE; StoreIndex: number; - Store: STORE; + Store: KMX.STORE; }; ResetOpt?: { StoreIndex: number; - Store: STORE; + Store: KMX.STORE; }; SaveOpt?: { StoreIndex: number; - Store: STORE; + Store: KMX.STORE; }; ChrVal?: number; }; -export function ExpandSentinel(fk: KEYBOARD, pwsz: string, x: number): TSentinelRecord { +export function ExpandSentinel(fk: KMX.KEYBOARD, pwsz: string, x: number): TSentinelRecord { let result: TSentinelRecord = { IsSentinel: false }; - if(pwsz.charCodeAt(x) == KMXFile.UC_SENTINEL) { + if(pwsz.charCodeAt(x) == KMX.KMXFile.UC_SENTINEL) { result.IsSentinel = true; x++; result.Code = pwsz.charCodeAt(x); x++; switch(result.Code) { - case KMXFile.CODE_ANY: - case KMXFile.CODE_NOTANY: // I3981 - result.Any.StoreIndex = pwsz.charCodeAt(x) - 1; - result.Any.Store = fk.stores[result.Any.StoreIndex]; + case KMX.KMXFile.CODE_ANY: + case KMX.KMXFile.CODE_NOTANY: // I3981 + let anyIdx = pwsz.charCodeAt(x) - 1; + result.Any = { + StoreIndex: anyIdx, + Store: fk.stores[anyIdx] + } break; - case KMXFile.CODE_INDEX: - result.Index.StoreIndex = pwsz.charCodeAt(x) - 1; - result.Index.Store = fk.stores[result.Index.StoreIndex]; + case KMX.KMXFile.CODE_INDEX: + let indexIdx = pwsz.charCodeAt(x) - 1; x++; - result.Index.Index = pwsz.charCodeAt(x); + result.Index = { + StoreIndex: indexIdx, + Store: fk.stores[indexIdx], + Index: pwsz.charCodeAt(x) - 1 + } break; - case KMXFile.CODE_DEADKEY: - result.DeadKey.DeadKey = pwsz.charCodeAt(x) - 1; + case KMX.KMXFile.CODE_DEADKEY: + result.DeadKey = { DeadKey: pwsz.charCodeAt(x) - 1 }; break; - case KMXFile.CODE_USE: - result.Use.GroupIndex = pwsz.charCodeAt(x) - 1; - result.Use.Group = fk.groups[result.Use.GroupIndex]; + case KMX.KMXFile.CODE_USE: + let useIdx = pwsz.charCodeAt(x) - 1; + result.Use = { + GroupIndex: useIdx, + Group: fk.groups[useIdx] + }; break; - case KMXFile.CODE_CALL: - result.Call.StoreIndex = pwsz.charCodeAt(x) - 1; - result.Call.Store = fk.stores[result.Call.StoreIndex]; + case KMX.KMXFile.CODE_CALL: + let callIdx = pwsz.charCodeAt(x) - 1; + result.Call = { + StoreIndex: callIdx, + Store: fk.stores[callIdx] + } break; - case KMXFile.CODE_CONTEXTEX: - result.ContextEx.Index = pwsz.charCodeAt(x); + case KMX.KMXFile.CODE_CONTEXTEX: + result.ContextEx = { Index: pwsz.charCodeAt(x) - 1 }; break; - case KMXFile.CODE_SETOPT: // I3429 - result.SetOpt.StoreIndex1 = pwsz.charCodeAt(x) - 1; - result.SetOpt.Store1 = fk.stores[result.SetOpt.StoreIndex1]; + case KMX.KMXFile.CODE_SETOPT: // I3429 + let setIdx1 = pwsz.charCodeAt(x) - 1; x++; - result.SetOpt.StoreIndex2 = pwsz.charCodeAt(x) - 1; - result.SetOpt.Store2 = fk.stores[result.SetOpt.StoreIndex2]; + let setIdx2 = pwsz.charCodeAt(x) - 1; + result.SetOpt = { + StoreIndex1: setIdx1, + Store1: fk.stores[setIdx1], + StoreIndex2: setIdx2, + Store2: fk.stores[setIdx2] + }; break; - case KMXFile.CODE_SETSYSTEMSTORE: // I3437 - result.SetSystemStore.dwSystemID = pwsz.charCodeAt(x) - 1; - result.SetSystemStore.SystemStore = fk.stores.find(s => s.dwSystemID == result.SetSystemStore.dwSystemID) || null; + case KMX.KMXFile.CODE_SETSYSTEMSTORE: // I3437 + let setsIdx1 = pwsz.charCodeAt(x) - 1; x++; - result.SetSystemStore.StoreIndex = pwsz.charCodeAt(x) - 1; - result.SetSystemStore.Store = fk.stores[result.SetSystemStore.StoreIndex]; + let setsIdx2 = pwsz.charCodeAt(x) - 1; + result.SetSystemStore = { + dwSystemID: setsIdx1, + SystemStore: fk.stores.find(s => s.dwSystemID == setsIdx1) || null, + StoreIndex: setsIdx2, + Store: fk.stores[setsIdx2] + }; break; - case KMXFile.CODE_RESETOPT: // I3429 - result.ResetOpt.StoreIndex = pwsz.charCodeAt(x) - 1; - result.ResetOpt.Store = fk.stores[result.ResetOpt.StoreIndex]; + case KMX.KMXFile.CODE_RESETOPT: // I3429 + result.ResetOpt = { + StoreIndex: pwsz.charCodeAt(x) - 1, + Store: fk.stores[result.ResetOpt.StoreIndex] + }; break; - case KMXFile.CODE_SAVEOPT: // I3429 - result.SaveOpt.StoreIndex = pwsz.charCodeAt(x) - 1; - result.SaveOpt.Store = fk.stores[result.SaveOpt.StoreIndex]; + case KMX.KMXFile.CODE_SAVEOPT: // I3429 + result.SaveOpt = { + StoreIndex: pwsz.charCodeAt(x) - 1, + Store: fk.stores[result.SaveOpt.StoreIndex] + }; break; - case KMXFile.CODE_IFOPT: // I3429 - result.IfOpt.StoreIndex1 = pwsz.charCodeAt(x) - 1; - result.IfOpt.Store1 = fk.stores[result.IfOpt.StoreIndex1]; + case KMX.KMXFile.CODE_IFOPT: // I3429 + let ifIdx1 = pwsz.charCodeAt(x) - 1; x++; - result.IfOpt.IsNot = pwsz.charCodeAt(x) - 1; // I3429 + let ifNot = pwsz.charCodeAt(x) - 1; x++; - result.IfOpt.StoreIndex2 = pwsz.charCodeAt(x) - 1; - result.IfOpt.Store2 = fk.stores[result.IfOpt.StoreIndex2]; + let ifIdx2 = pwsz.charCodeAt(x) - 1; + result.IfOpt = { + StoreIndex1: ifIdx1, + Store1: fk.stores[ifIdx1], + IsNot: ifNot, // I3429 + StoreIndex2: ifIdx2, + Store2: fk.stores[ifIdx2] + }; break; - case KMXFile.CODE_IFSYSTEMSTORE: // I3430 - result.IfSystemStore.dwSystemID = pwsz.charCodeAt(x) - 1; - result.IfSystemStore.SystemStore = fk.stores.find(s => s.dwSystemID == result.IfSystemStore.dwSystemID) || null; + case KMX.KMXFile.CODE_IFSYSTEMSTORE: // I3430 + let ifsSystemID = pwsz.charCodeAt(x) - 1; x++; - result.IfSystemStore.IsNot = pwsz.charCodeAt(x) - 1; // I3430 + let ifsNot = pwsz.charCodeAt(x) - 1; x++; - result.IfSystemStore.StoreIndex = pwsz.charCodeAt(x) - 1; - result.IfSystemStore.Store = fk.stores[result.IfSystemStore.StoreIndex]; + let ifsIdx2 = pwsz.charCodeAt(x) - 1; + result.IfSystemStore = { + dwSystemID: ifsSystemID, + SystemStore: fk.stores.find(s => s.dwSystemID == ifsSystemID) || null, + IsNot: ifsNot, + StoreIndex: ifsIdx2, + Store: fk.stores[ifsIdx2] + }; + break; + case KMX.KMXFile.CODE_NUL: + case KMX.KMXFile.CODE_CONTEXT: + case KMX.KMXFile.CODE_RETURN: + case KMX.KMXFile.CODE_BEEP: + case KMX.KMXFile.CODE_EXTENDED: + // No additional detail needed, or outside scope break; default: throw new Error(`Unrecognized system store value ${result.Code}`); @@ -167,7 +208,7 @@ export function incxstr(p: string, x: number): number { } let ch = p.charCodeAt(x); - if(ch != KMXFile.UC_SENTINEL) { + if(ch != KMX.KMXFile.UC_SENTINEL) { if(ch >= 0xD800 && ch <= 0xDBFF) { x++; if(x == p.length) { @@ -190,27 +231,28 @@ export function incxstr(p: string, x: number): number { } switch(p.charCodeAt(x)) { - case KMXFile.CODE_ANY: x += 2; break; - case KMXFile.CODE_INDEX: x += 3; break; - case KMXFile.CODE_USE: x += 2; break; - case KMXFile.CODE_DEADKEY: x += 2; break; - case KMXFile.CODE_EXTENDED: + case KMX.KMXFile.CODE_ANY: x += 2; break; + case KMX.KMXFile.CODE_INDEX: x += 3; break; + case KMX.KMXFile.CODE_USE: x += 2; break; + case KMX.KMXFile.CODE_DEADKEY: x += 2; break; + case KMX.KMXFile.CODE_EXTENDED: x += 3; - while(x <= p.length && p.charCodeAt(x) != KMXFile.UC_SENTINEL_EXTENDEDEND) { + while(x <= p.length && p.charCodeAt(x) != KMX.KMXFile.UC_SENTINEL_EXTENDEDEND) { x++; } + x++; break; - case KMXFile.CODE_CALL: x += 2; break; - case KMXFile.CODE_CONTEXTEX: x += 2; break; - case KMXFile.CODE_NOTANY: x += 2; break; + case KMX.KMXFile.CODE_CALL: x += 2; break; + case KMX.KMXFile.CODE_CONTEXTEX: x += 2; break; + case KMX.KMXFile.CODE_NOTANY: x += 2; break; - case KMXFile.CODE_CLEARCONTEXT: x += 2; break; - case KMXFile.CODE_IFOPT: x += 4; break; - case KMXFile.CODE_IFSYSTEMSTORE: x += 4; break; - case KMXFile.CODE_SETOPT: x += 3; break; - case KMXFile.CODE_SETSYSTEMSTORE: x += 3; break; - case KMXFile.CODE_RESETOPT: x += 2; break; - case KMXFile.CODE_SAVEOPT: x += 2; break; + case KMX.KMXFile.CODE_CLEARCONTEXT: x += 2; break; + case KMX.KMXFile.CODE_IFOPT: x += 4; break; + case KMX.KMXFile.CODE_IFSYSTEMSTORE: x += 4; break; + case KMX.KMXFile.CODE_SETOPT: x += 3; break; + case KMX.KMXFile.CODE_SETSYSTEMSTORE: x += 3; break; + case KMX.KMXFile.CODE_RESETOPT: x += 2; break; + case KMX.KMXFile.CODE_SAVEOPT: x += 2; break; default: x++; } @@ -234,12 +276,12 @@ export function xstrlen(p: string): number { export function xstrlen_printing(p: string): number { let result = 0, x = 0; while(x < p.length) { - if(x + 1 < p.length && p.charCodeAt(x) == KMXFile.UC_SENTINEL) { + if(x + 1 < p.length && p.charCodeAt(x) == KMX.KMXFile.UC_SENTINEL) { switch(p.charCodeAt(x+1)) { - case KMXFile.CODE_DEADKEY: - case KMXFile.CODE_NUL: - case KMXFile.CODE_IFOPT: - case KMXFile.CODE_IFSYSTEMSTORE: + case KMX.KMXFile.CODE_DEADKEY: + case KMX.KMXFile.CODE_NUL: + case KMX.KMXFile.CODE_IFOPT: + case KMX.KMXFile.CODE_IFSYSTEMSTORE: result--; break; } diff --git a/developer/src/kmc-kmw/test/README.md b/developer/src/kmc-kmw/test/README.md new file mode 100644 index 0000000000..e1ccf019ac --- /dev/null +++ b/developer/src/kmc-kmw/test/README.md @@ -0,0 +1,7 @@ +Keyman kmn kmw Keyboard Compiler Tests +====================================== + +Test +---- + + ../build.sh test diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.ico b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.ico new file mode 100644 index 0000000000000000000000000000000000000000..42c90c398daf08f560778dd383cc0f7dd5922ae1 GIT binary patch literal 1150 zcmd^7J<7sB5PkA_fE4n9ogjjR=shgO&I@=AJDU_~?d&Ziq|ByFAdpQ`B*Z2}kB}2M zGfnj4Gb)zO@^;?t+c*2e0v&3GF#yN93;a?Z6AZ$D(2<@9X@6rs{lPb5gbEGL#9zU! zr{Q&7gHctLWUV!lBoSVgrDWEd{TeUN4RJ!6rtmxud7i_zZ8(l2Tqz|QuX*I>dEO_E zV+28fEXxGG?<0yL(b~MM6-5E9BWyPZn5GHKvV@0WD7BvXN4Q|tKgb!Ca^bqJ@Ja7T encw#Q&TZq>Vu$5?_m-!v-hbLR|9!sur*Q?n;~upD literal 0 HcmV?d00001 diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.js b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.js new file mode 100644 index 0000000000..e2296a99e8 --- /dev/null +++ b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.js @@ -0,0 +1,5463 @@ +if(typeof keyman === 'undefined') { + console.log('Keyboard requires KeymanWeb 10.0 or later'); + if(typeof tavultesoft !== 'undefined') tavultesoft.keymanweb.util.alert("This keyboard requires KeymanWeb 10.0 or later"); +} else { +KeymanWeb.KR(new Keyboard_khmer_angkor()); +} +function Keyboard_khmer_angkor() +{ + var modCodes = keyman.osk.modifierCodes; + var keyCodes = keyman.osk.keyCodes; + + this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9; + this.KI="Keyboard_khmer_angkor"; + this.KN="Khmer Angkor"; + this.KMINVER="10.0"; + this.KV={F:' 1em "Khmer Busra Kbd"',K102:0}; + this.KV.KLS={ + "rightalt": ["‍","‌","@","","$","€","៙","៚","*","{","}","≈","","","","","ៜ","","ឯ","ឫ","ឨ","[","]","ឦ","ឱ","ឰ","ឩ","ឳ","\\","","","","+","-","×","÷",":","‘","’","ឝ","៘","៖","ៈ","","","","","","","<",">","#","&","ឞ",";","",",",".","/","","","","",""," "], + "rightalt-shift": ["","៱","៲","៳","៴","៵","៶","៷","៸","៹","៰","","","","","","᧠","᧡","᧢","᧣","᧤","᧥","᧦","᧧","᧨","᧩","᧪","᧫","","","","","᧬","᧭","᧮","᧯","᧰","᧱","᧲","᧳","᧴","᧵","᧶","","","","","","","᧷","᧸","᧹","᧺","᧻","᧼","᧽","᧾","᧿","","","","","","",""], + "default": ["«","១","២","៣","៤","៥","៦","៧","៨","៩","០","ឥ","ឲ","","","","ឆ","","","រ","ត","យ","","","","ផ","","ឪ","ឮ","","","","","ស","ដ","ថ","ង","ហ","","ក","ល","","","","","","","","","ឋ","ខ","ច","វ","ប","ន","ម","","។","","","","","","","​"], + "shift": ["»","!","ៗ","\"","៛","%","","","","(",")","","=","","","","ឈ","","","ឬ","ទ","","","","","ភ","","ឧ","ឭ","","","","","","ឌ","ធ","អ","ះ","ញ","គ","ឡ","","","","","","","","","ឍ","ឃ","ជ","","ព","ណ","","","៕","?","","","","","",""] + }; + this.KV.BK=(function(x){ + var + empty=Array.apply(null, Array(65)).map(String.prototype.valueOf,""), + result=[], v, i, + modifiers=['default','shift','ctrl','shift-ctrl','alt','shift-alt','ctrl-alt','shift-ctrl-alt']; + for(i=modifiers.length-1;i>=0;i--) { + v = x[modifiers[i]]; + if(v || result.length > 0) { + result=(v ? v : empty).slice().concat(result); + } + } + return result; + })(this.KV.KLS); + this.KDU=0; + this.KH=''; + this.KM=0; + this.KBVER="1.3"; + this.KMBM=modCodes.RALT | modCodes.SHIFT /* 0x0018 */; + this.KVKD="T_17D2_1780 T_17D2_1781 T_17D2_1782 T_17D2_1783 T_17D2_1784 T_17D2_1785 T_17D2_1786 T_17D2_1787 T_17D2_1788 T_17D2_1789 T_17D2_178A T_17D2_178B T_17D2_178C T_17D2_178D T_17D2_178E T_17D2_178F T_17D2_1790 T_17D2_1791 T_17D2_1792 T_17D2_1793 T_17D2_1794 T_17D2_1795 T_17D2_1796 T_17D2_1797 T_17D2_1798 T_17D2_1799 T_17D2_179A T_17D2_179B T_17D2_179C T_17D2_179D T_17D2_179E T_17D2_179F T_17D2_17A0 T_17D2_17A1 T_17D2_17A2 U_0030 U_0031 U_0032 U_0033 U_0034 U_0035 U_0036 U_0037 U_0038 U_0039"; + this.KVKL={ + "phone": { + "font": "Khmer Busra Kbd", + "fontsize": "0.8em", + "displayUnderlying": false, + "layer": [ + { + "id": "default", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_Q", + "text": "\u1786", + "sk": [ + { + "layer": "shift", + "id": "K_Q", + "text": "\u1788" + }, + { + "id": "T_17D2_1786", + "text": "\uEF86" + }, + { + "id": "T_17D2_1788", + "text": "\uEF88" + } + ] + }, + { + "id": "K_W", + "text": "\uEFB9", + "sk": [ + { + "layer": "shift", + "id": "K_W", + "text": "\uEFBA" + } + ] + }, + { + "id": "K_E", + "text": "\uEFC1", + "sk": [ + { + "layer": "shift", + "id": "K_E", + "text": "\uEFC2" + }, + { + "layer": "shift", + "id": "K_S", + "text": "\uEFC3" + }, + { + "layer": "shift", + "id": "K_V", + "text": "\uEF12" + }, + { + "id": "U_17AF", + "text": "\u17AF" + }, + { + "id": "U_17B0", + "text": "\u17B0" + } + ] + }, + { + "id": "K_R", + "text": "\u179A", + "sk": [ + { + "id": "T_17D2_179A", + "text": "\uEF9A" + }, + { + "id": "U_17AB", + "text": "\u17AB" + }, + { + "id": "U_17AC", + "text": "\u17AC" + } + ] + }, + { + "id": "K_T", + "text": "\u178F", + "sk": [ + { + "layer": "shift", + "id": "K_T", + "text": "\u1791" + }, + { + "id": "T_17D2_178F", + "text": "\uEF8F" + }, + { + "layer": "default", + "id": "T_17D2_1791", + "text": "\uEF91" + } + ] + }, + { + "id": "K_Y", + "text": "\u1799", + "sk": [ + { + "id": "T_17D2_1799", + "text": "\uEF99" + } + ] + }, + { + "id": "K_U", + "text": "\uEFBB", + "sk": [ + { + "layer": "shift", + "id": "K_U", + "text": "\uEFBC" + }, + { + "layer": "shift", + "id": "K_Y", + "text": "\uEFBD" + }, + { + "id": "U_17A7", + "text": "\u17A7" + }, + { + "layer": "shift", + "id": "U_17AA", + "text": "\u17AA" + }, + { + "layer": "shift", + "id": "U_17A9", + "text": "\u17A9" + }, + { + "id": "U_17A8", + "text": "\u17A8" + } + ] + }, + { + "id": "K_I", + "text": "\uEFB7", + "sk": [ + { + "layer": "shift", + "id": "K_I", + "text": "\uEFB8" + }, + { + "id": "U_17A5", + "text": "\u17A5" + }, + { + "layer": "shift", + "id": "U_17A6", + "text": "\u17A6" + } + ] + }, + { + "id": "K_O", + "text": "\uEFC4", + "sk": [ + { + "layer": "shift", + "id": "K_O", + "text": "\uEFC5" + }, + { + "id": "K_LBRKT", + "text": "\uEFC0" + }, + { + "layer": "shift", + "id": "K_LBRKT", + "text": "\uEFBF" + }, + { + "layer": "shift", + "id": "K_COLON", + "text": "\uEF14" + }, + { + "id": "U_17B1", + "text": "\u17B1" + }, + { + "id": "U_17B2", + "text": "\u17B2" + }, + { + "layer": "shift", + "id": "U_17B3", + "text": "\u17B3" + } + ] + }, + { + "id": "K_P", + "text": "\u1795", + "sk": [ + { + "layer": "shift", + "id": "K_P", + "text": "\u1797" + }, + { + "id": "T_17D2_1795", + "text": "\uEF95" + }, + { + "layer": "default", + "id": "T_17D2_1797", + "text": "\uEF97" + } + ] + } + ] + }, + { + "id": "2", + "key": [ + { + "width": "100", + "id": "K_A", + "text": "\uEFB6", + "sk": [ + { + "layer": "shift", + "id": "K_A", + "text": "\uEF11" + } + ] + }, + { + "id": "K_S", + "text": "\u179F", + "sk": [ + { + "id": "T_17D2_179F", + "text": "\uEF9F" + }, + { + "id": "U_179D", + "text": "\u179D" + }, + { + "id": "U_179E", + "text": "\u179E" + } + ] + }, + { + "id": "K_D", + "text": "\u178A", + "sk": [ + { + "layer": "shift", + "id": "K_D", + "text": "\u178C" + }, + { + "id": "T_17D2_178A", + "text": "\uEF8A" + }, + { + "layer": "default", + "id": "T_17D2_178C", + "text": "\uEF8C" + } + ] + }, + { + "id": "K_F", + "text": "\u1790", + "sk": [ + { + "layer": "shift", + "id": "K_F", + "text": "\u1792" + }, + { + "id": "T_17D2_1790", + "text": "\uEF90" + }, + { + "layer": "default", + "id": "T_17D2_1792", + "text": "\uEF92" + } + ] + }, + { + "id": "K_G", + "text": "\u1784", + "sk": [ + { + "layer": "shift", + "id": "K_G", + "text": "\u17A2" + }, + { + "id": "T_17D2_1784", + "text": "\uEF84" + }, + { + "layer": "default", + "id": "T_17D2_17A2", + "text": "\uEFA2" + } + ] + }, + { + "id": "K_H", + "text": "\u17A0", + "sk": [ + { + "id": "T_17D2_17A0", + "text": "\uEFA0" + }, + { + "layer": "shift", + "id": "K_H", + "text": "\u17C7" + }, + { + "id": "U_17C8", + "text": "\u17C8" + } + ] + }, + { + "layer": "shift", + "id": "K_J", + "text": "\u1789", + "sk": [ + { + "id": "T_17D2_1789", + "text": "\uEF89" + } + ] + }, + { + "id": "K_K", + "text": "\u1780", + "sk": [ + { + "layer": "shift", + "id": "K_K", + "text": "\u1782" + }, + { + "id": "T_17D2_1780", + "text": "\uEF80" + }, + { + "id": "T_17D2_1782", + "text": "\uEF82" + } + ] + }, + { + "id": "K_L", + "text": "\u179B", + "sk": [ + { + "layer": "shift", + "id": "K_L", + "text": "\u17A1" + }, + { + "id": "T_17D2_179B", + "text": "\uEF9B" + }, + { + "id": "U_17AD", + "text": "\u17AD" + }, + { + "id": "U_17AE", + "text": "\u17AE" + } + ] + }, + { + "id": "K_COLON", + "text": "\uEFBE" + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_Z", + "text": "\u178B", + "sk": [ + { + "layer": "shift", + "id": "K_Z", + "text": "\u178D" + }, + { + "id": "T_17D2_178B", + "text": "\uEF8B" + }, + { + "layer": "default", + "id": "T_17D2_178D", + "text": "\uEF8D" + } + ] + }, + { + "id": "K_X", + "text": "\u1781", + "sk": [ + { + "layer": "shift", + "id": "K_X", + "text": "\u1783" + }, + { + "id": "T_17D2_1781", + "text": "\uEF81" + }, + { + "layer": "default", + "id": "T_17D2_1783", + "text": "\uEF83" + } + ] + }, + { + "id": "K_C", + "text": "\u1785", + "sk": [ + { + "layer": "shift", + "id": "K_C", + "text": "\u1787" + }, + { + "id": "T_17D2_1785", + "text": "\uEF85" + }, + { + "layer": "default", + "id": "T_17D2_1787", + "text": "\uEF87" + } + ] + }, + { + "id": "K_V", + "text": "\u179C", + "sk": [ + { + "id": "T_17D2_179C", + "text": "\uEF9C" + } + ] + }, + { + "id": "K_B", + "text": "\u1794", + "sk": [ + { + "layer": "shift", + "id": "K_B", + "text": "\u1796" + }, + { + "id": "T_17D2_1794", + "text": "\uEF94" + }, + { + "layer": "default", + "id": "T_17D2_1796", + "text": "\uEF96" + } + ] + }, + { + "id": "K_N", + "text": "\u1793", + "sk": [ + { + "layer": "shift", + "id": "K_N", + "text": "\u178E" + }, + { + "id": "T_17D2_1793", + "text": "\uEF93" + }, + { + "layer": "default", + "id": "T_17D2_178E", + "text": "\uEF8E" + } + ] + }, + { + "id": "K_M", + "text": "\u1798", + "sk": [ + { + "id": "T_17D2_1798", + "text": "\uEF98" + }, + { + "layer": "shift", + "id": "K_M", + "text": "\uEFC6" + } + ] + }, + { + "id": "K_COMMA", + "text": "\uEF10", + "sk": [ + { + "layer": "shift", + "id": "K_COMMA", + "text": "\uEF13" + }, + { + "layer": "shift", + "id": "K_6", + "text": "\uEFCD" + }, + { + "layer": "shift", + "id": "K_7", + "text": "\uEFD0" + }, + { + "layer": "shift", + "id": "K_8", + "text": "\uEFCF" + }, + { + "layer": "shift", + "id": "K_HYPHEN", + "text": "\uEFCC" + }, + { + "layer": "shift", + "id": "U_17D1", + "text": "\uEFD1" + }, + { + "layer": "shift", + "id": "U_17DD", + "text": "\uEFDD" + }, + { + "layer": "shift", + "id": "U_17CE", + "text": "\uEFCE" + } + ] + }, + { + "width": "100", + "id": "K_QUOTE", + "text": "\uEFCB", + "sk": [ + { + "layer": "shift", + "id": "K_QUOTE", + "text": "\uEFC9" + }, + { + "id": "K_SLASH", + "text": "\uEFCA" + } + ] + }, + { + "width": "100", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "numeric", + "width": "140", + "id": "K_NUMLOCK", + "sp": "1", + "text": "\u17E1\u17E2\u17E3" + }, + { + "width": "120", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "width": "555", + "id": "K_SPACE", + "text": "\u200B", + "sk": [ + { + "layer": "default", + "id": "U_0020", + "text": " " + } + ] + }, + { + "width": "120", + "id": "K_PERIOD", + "text": "\u17D4", + "sk": [ + { + "layer": "shift", + "id": "K_PERIOD", + "text": "\u17D5" + }, + { + "id": "U_0021", + "text": "!" + }, + { + "id": "U_003F", + "text": "?" + } + ] + }, + { + "width": "140", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + }, + { + "id": "numeric", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_1", + "text": "\u17E1", + "sk": [ + { + "id": "U_0031", + "text": "1" + } + ] + }, + { + "id": "K_2", + "text": "\u17E2", + "sk": [ + { + "id": "U_0032", + "text": "2" + } + ] + }, + { + "id": "K_3", + "text": "\u17E3", + "sk": [ + { + "id": "U_0033", + "text": "3" + } + ] + }, + { + "id": "K_4", + "text": "\u17E4", + "sk": [ + { + "id": "U_0034", + "text": "4" + } + ] + }, + { + "id": "K_5", + "text": "\u17E5", + "sk": [ + { + "id": "U_0035", + "text": "5" + } + ] + }, + { + "id": "K_6", + "text": "\u17E6", + "sk": [ + { + "id": "U_0036", + "text": "6" + } + ] + }, + { + "id": "K_7", + "text": "\u17E7", + "sk": [ + { + "id": "U_0037", + "text": "7" + } + ] + }, + { + "id": "K_8", + "text": "\u17E8", + "sk": [ + { + "id": "U_0038", + "text": "8" + } + ] + }, + { + "id": "K_9", + "text": "\u17E9", + "sk": [ + { + "id": "U_0039", + "text": "9" + } + ] + }, + { + "id": "K_0", + "text": "\u17E0", + "sk": [ + { + "id": "U_0030", + "text": "0" + }, + { + "id": "U_17D3", + "text": "\uEFD3" + } + ] + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "U_0040", + "text": "@", + "sk": [ + { + "id": "U_00A9", + "text": "\u00A9" + }, + { + "id": "U_00AE", + "text": "\u00AE" + } + ] + }, + { + "id": "U_0023", + "text": "#", + "sk": [ + { + "id": "U_2116", + "text": "\u2116" + }, + { + "id": "U_007E", + "text": "~" + } + ] + }, + { + "id": "U_17DB", + "text": "\u17DB", + "sk": [ + { + "id": "U_0024", + "text": "$" + }, + { + "id": "U_0E3F", + "text": "\u0E3F" + }, + { + "id": "U_00A2", + "text": "\u00A2" + }, + { + "id": "U_00A3", + "text": "\u00A3" + }, + { + "id": "U_00A5", + "text": "\u00A5" + } + ] + }, + { + "id": "U_0026", + "text": "&" + }, + { + "id": "U_0025", + "text": "%", + "sk": [ + { + "id": "U_2030", + "text": "\u2030" + }, + { + "id": "U_2031", + "text": "\u2031" + } + ] + }, + { + "id": "U_002B", + "text": "+", + "sk": [ + { + "id": "U_002D", + "text": "-" + }, + { + "id": "U_00D7", + "text": "\u00D7" + }, + { + "id": "U_00F7", + "text": "\u00F7" + }, + { + "id": "U_00B1", + "text": "\u00B1" + } + ] + }, + { + "id": "U_003D", + "text": "=", + "sk": [ + { + "id": "U_005F", + "text": "_" + }, + { + "id": "U_2260", + "text": "\u2260" + } + ] + }, + { + "id": "U_002A", + "text": "*", + "sk": [ + { + "id": "U_005E", + "text": "^" + } + ] + }, + { + "id": "U_003F", + "text": "?", + "sk": [ + { + "id": "U_00BF", + "text": "\u00BF" + } + ] + }, + { + "id": "U_0021", + "text": "!", + "sk": [ + { + "id": "U_00A1", + "text": "\u00A1" + } + ] + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "U_2018", + "text": "\u2018", + "sk": [ + { + "id": "U_2019", + "text": "\u2019" + } + ] + }, + { + "id": "U_201C", + "text": "\u201C", + "sk": [ + { + "id": "U_201D", + "text": "\u201D" + } + ] + }, + { + "id": "U_00AB", + "text": "\u00AB", + "sk": [ + { + "id": "U_00BB", + "text": "\u00BB" + } + ] + }, + { + "id": "U_002F", + "text": "/", + "sk": [ + { + "id": "U_005C", + "text": "\\" + }, + { + "id": "U_007C", + "text": "|" + }, + { + "id": "U_00A6", + "text": "\u00A6" + } + ] + }, + { + "id": "U_0028", + "text": "(", + "sk": [ + { + "id": "U_0029", + "text": ")" + }, + { + "id": "U_005B", + "text": "[" + }, + { + "id": "U_005D", + "text": "]" + }, + { + "id": "U_007B", + "text": "{" + }, + { + "id": "U_007D", + "text": "}" + } + ] + }, + { + "id": "U_17D9", + "text": "\u17D9", + "sk": [ + { + "id": "U_17DA", + "text": "\u17DA" + }, + { + "id": "U_17DC", + "text": "\u17DC" + }, + { + "id": "U_00A7", + "text": "\u00A7" + }, + { + "id": "U_00D8", + "text": "\u00D8" + } + ] + }, + { + "id": "U_17D7", + "text": "\u17D7" + }, + { + "id": "U_003C", + "text": "<", + "sk": [ + { + "id": "U_2264", + "text": "\u2264" + }, + { + "id": "U_003E", + "text": ">" + }, + { + "id": "U_2265", + "text": "\u2265" + } + ] + }, + { + "id": "U_17D6", + "text": "\u17D6", + "sk": [ + { + "id": "U_003A", + "text": ":" + }, + { + "id": "U_003B", + "text": ";" + }, + { + "id": "U_2026", + "text": "\u2026" + } + ] + }, + { + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "default", + "width": "140", + "id": "K_LCONTROL", + "sp": "2", + "text": "\u17E1\u17E2\u17E3" + }, + { + "width": "120", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "layer": "shift", + "width": "555", + "id": "K_SPACE", + "text": "\u200B" + }, + { + "width": "120", + "id": "K_PERIOD", + "text": "\u17D4", + "sk": [ + { + "layer": "shift", + "id": "K_PERIOD", + "text": "\u17D5" + }, + { + "id": "U_0021", + "text": "!" + }, + { + "id": "U_003F", + "text": "?" + } + ] + }, + { + "width": "140", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + } + ] + }, + "tablet": { + "font": "Khmer Busra Kbd", + "fontsize": "0.8em", + "displayUnderlying": false, + "layer": [ + { + "id": "default", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_1", + "text": "\u17E1" + }, + { + "id": "K_2", + "text": "\u17E2" + }, + { + "id": "K_3", + "text": "\u17E3" + }, + { + "id": "K_4", + "text": "\u17E4" + }, + { + "id": "K_5", + "text": "\u17E5" + }, + { + "id": "K_6", + "text": "\u17E6" + }, + { + "id": "K_7", + "text": "\u17E7" + }, + { + "id": "K_8", + "text": "\u17E8" + }, + { + "id": "K_9", + "text": "\u17E9" + }, + { + "id": "K_0", + "text": "\u17E0" + }, + { + "id": "K_HYPHEN", + "text": "\u17A5" + }, + { + "id": "K_EQUAL", + "text": "\u17B2" + }, + { + "width": "100", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "K_Q", + "pad": "75", + "text": "\u1786" + }, + { + "id": "K_W", + "text": "\uEFB9" + }, + { + "id": "K_E", + "text": "\uEFC1" + }, + { + "id": "K_R", + "text": "\u179A" + }, + { + "id": "K_T", + "text": "\u178F" + }, + { + "id": "K_Y", + "text": "\u1799" + }, + { + "id": "K_U", + "text": "\uEFBB" + }, + { + "id": "K_I", + "text": "\uEFB7" + }, + { + "id": "K_O", + "text": "\uEFC4" + }, + { + "id": "K_P", + "text": "\u1795" + }, + { + "id": "K_LBRKT", + "text": "\uEFC0" + }, + { + "id": "K_RBRKT", + "text": "\u17AA" + }, + { + "width": "10", + "id": "T_new_138", + "sp": "10" + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_BKQUOTE", + "text": "\u00AB" + }, + { + "id": "K_A", + "text": "\uEFB6" + }, + { + "id": "K_S", + "text": "\u179F" + }, + { + "id": "K_D", + "text": "\u178A" + }, + { + "id": "K_F", + "text": "\u1790" + }, + { + "id": "K_G", + "text": "\u1784" + }, + { + "id": "K_H", + "text": "\u17A0" + }, + { + "id": "K_J", + "text": "\uEFD2" + }, + { + "id": "K_K", + "text": "\u1780" + }, + { + "id": "K_L", + "text": "\u179B" + }, + { + "id": "K_COLON", + "text": "\uEFBE" + }, + { + "id": "K_QUOTE", + "text": "\uEFCB" + }, + { + "id": "K_BKSLASH", + "text": "\u17AE" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "shift", + "width": "160", + "id": "K_SHIFT", + "sp": "1", + "text": "*Shift*" + }, + { + "id": "K_oE2" + }, + { + "id": "K_Z", + "text": "\u178B" + }, + { + "id": "K_X", + "text": "\u1781" + }, + { + "id": "K_C", + "text": "\u1785" + }, + { + "id": "K_V", + "text": "\u179C" + }, + { + "id": "K_B", + "text": "\u1794" + }, + { + "id": "K_N", + "text": "\u1793" + }, + { + "id": "K_M", + "text": "\u1798" + }, + { + "id": "K_COMMA", + "text": "\uEF10" + }, + { + "id": "K_PERIOD", + "text": "\u17D4" + }, + { + "id": "K_SLASH", + "text": "\uEFCA" + }, + { + "width": "10", + "id": "T_new_164", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "rightalt", + "width": "160", + "id": "K_LCONTROL", + "sp": "1", + "text": "*AltGr*" + }, + { + "width": "160", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "width": "930", + "id": "K_SPACE", + "text": "\u200B" + }, + { + "width": "160", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + }, + { + "id": "rightalt", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_1", + "text": "\u200C" + }, + { + "id": "K_2", + "text": "@" + }, + { + "id": "K_3", + "text": "\uEFD1" + }, + { + "id": "K_4", + "text": "$" + }, + { + "id": "K_5", + "text": "\u20AC" + }, + { + "id": "K_6", + "text": "\u17D9" + }, + { + "id": "K_7", + "text": "\u17DA" + }, + { + "id": "K_8", + "text": "*" + }, + { + "id": "K_9", + "text": "{" + }, + { + "id": "K_0", + "text": "}" + }, + { + "id": "K_HYPHEN", + "text": "\u2248" + }, + { + "id": "K_EQUAL", + "text": "\uEFCE" + }, + { + "width": "100", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "K_Q", + "pad": "75", + "text": "\u17DC" + }, + { + "id": "K_W", + "text": "\uEFDD" + }, + { + "id": "K_E", + "text": "\u17AF" + }, + { + "id": "K_R", + "text": "\u17AB" + }, + { + "id": "K_T", + "text": "\u17A8" + }, + { + "id": "K_Y", + "text": "[" + }, + { + "id": "K_U", + "text": "]" + }, + { + "id": "K_I", + "text": "\u17A6" + }, + { + "id": "K_O", + "text": "\u17B1" + }, + { + "id": "K_P", + "text": "\u17B0" + }, + { + "id": "K_LBRKT", + "text": "\u17A9" + }, + { + "id": "K_RBRKT", + "text": "\u17B3" + }, + { + "width": "10", + "id": "T_new_307", + "sp": "10" + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_BKQUOTE", + "text": "\u200D" + }, + { + "id": "K_A", + "text": "+" + }, + { + "id": "K_S", + "text": "-" + }, + { + "id": "K_D", + "text": "\u00D7" + }, + { + "id": "K_F", + "text": "\u00F7" + }, + { + "id": "K_G", + "text": ":" + }, + { + "id": "K_H", + "text": "\u2018" + }, + { + "id": "K_J", + "text": "\u2019" + }, + { + "id": "K_K", + "text": "\u179D" + }, + { + "id": "K_L", + "text": "\u17D8" + }, + { + "id": "K_COLON", + "text": "\u17D6" + }, + { + "id": "K_QUOTE", + "text": "\u17C8" + }, + { + "id": "K_BKSLASH", + "text": "\\" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "shift", + "width": "160", + "id": "K_SHIFT", + "sp": "1", + "text": "*Shift*" + }, + { + "id": "K_oE2" + }, + { + "id": "K_Z", + "text": "<" + }, + { + "id": "K_X", + "text": ">" + }, + { + "id": "K_C", + "text": "#" + }, + { + "id": "K_V", + "text": "&" + }, + { + "id": "K_B", + "text": "\u179E" + }, + { + "id": "K_N", + "text": ";" + }, + { + "id": "K_M", + "text": "\uEFD3" + }, + { + "id": "K_COMMA", + "text": "," + }, + { + "id": "K_PERIOD", + "text": "." + }, + { + "id": "K_SLASH", + "text": "/" + }, + { + "width": "10", + "id": "T_new_333", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "default", + "width": "160", + "id": "K_LCONTROL", + "sp": "2", + "text": "*AltGr*" + }, + { + "width": "160", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "width": "930", + "id": "K_SPACE", + "text": "\u00A0" + }, + { + "width": "160", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + }, + { + "id": "shift", + "row": [ + { + "id": "1", + "key": [ + { + "id": "K_1", + "text": "!" + }, + { + "id": "K_2", + "text": "\u17D7" + }, + { + "id": "K_3", + "text": "\"" + }, + { + "id": "K_4", + "text": "\u17DB" + }, + { + "id": "K_5", + "text": "%" + }, + { + "id": "K_6", + "text": "\uEFCD" + }, + { + "id": "K_7", + "text": "\uEFD0" + }, + { + "id": "K_8", + "text": "\uEFCF" + }, + { + "id": "K_9", + "text": "(" + }, + { + "id": "K_0", + "text": ")" + }, + { + "id": "K_HYPHEN", + "text": "\uEFCC" + }, + { + "id": "K_EQUAL", + "text": "=" + }, + { + "width": "100", + "id": "K_BKSP", + "sp": "1", + "text": "*BkSp*" + } + ] + }, + { + "id": "2", + "key": [ + { + "id": "K_Q", + "pad": "75", + "text": "\u1788" + }, + { + "id": "K_W", + "text": "\uEFBA" + }, + { + "id": "K_E", + "text": "\uEFC2" + }, + { + "id": "K_R", + "text": "\u17AC" + }, + { + "id": "K_T", + "text": "\u1791" + }, + { + "id": "K_Y", + "text": "\uEFBD" + }, + { + "id": "K_U", + "text": "\uEFBC" + }, + { + "id": "K_I", + "text": "\uEFB8" + }, + { + "id": "K_O", + "text": "\uEFC5" + }, + { + "id": "K_P", + "text": "\u1797" + }, + { + "id": "K_LBRKT", + "text": "\uEFBF" + }, + { + "id": "K_RBRKT", + "text": "\u17A7" + }, + { + "width": "10", + "id": "T_new_364", + "sp": "10" + } + ] + }, + { + "id": "3", + "key": [ + { + "id": "K_BKQUOTE", + "text": "\u00BB" + }, + { + "id": "K_A", + "text": "\uEF11" + }, + { + "id": "K_S", + "text": "\uEFC3" + }, + { + "id": "K_D", + "text": "\u178C" + }, + { + "id": "K_F", + "text": "\u1792" + }, + { + "id": "K_G", + "text": "\u17A2" + }, + { + "id": "K_H", + "text": "\u17C7" + }, + { + "id": "K_J", + "text": "\u1789" + }, + { + "id": "K_K", + "text": "\u1782" + }, + { + "id": "K_L", + "text": "\u17A1" + }, + { + "id": "K_COLON", + "text": "\uEF14" + }, + { + "id": "K_QUOTE", + "text": "\uEFC9" + }, + { + "id": "K_BKSLASH", + "text": "\u17AD" + } + ] + }, + { + "id": "4", + "key": [ + { + "nextlayer": "default", + "width": "160", + "id": "K_SHIFT", + "sp": "2", + "text": "*Shift*" + }, + { + "id": "K_oE2" + }, + { + "id": "K_Z", + "text": "\u178D" + }, + { + "id": "K_X", + "text": "\u1783" + }, + { + "id": "K_C", + "text": "\u1787" + }, + { + "id": "K_V", + "text": "\uEF12" + }, + { + "id": "K_B", + "text": "\u1796" + }, + { + "id": "K_N", + "text": "\u178E" + }, + { + "id": "K_M", + "text": "\uEFC6" + }, + { + "id": "K_COMMA", + "text": "\uEF13" + }, + { + "id": "K_PERIOD", + "text": "\u17D5" + }, + { + "id": "K_SLASH", + "text": "?" + }, + { + "width": "10", + "id": "T_new_390", + "sp": "10" + } + ] + }, + { + "id": "5", + "key": [ + { + "nextlayer": "rightalt", + "width": "160", + "id": "K_LCONTROL", + "sp": "1", + "text": "*AltGr*" + }, + { + "width": "160", + "id": "K_LOPT", + "sp": "1", + "text": "*Menu*" + }, + { + "width": "930", + "id": "K_SPACE" + }, + { + "width": "160", + "id": "K_ENTER", + "sp": "1", + "text": "*Enter*" + } + ] + } + ] + } + ] + } +} +; + this.s_c_key_11=['','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','']; + this.s_c_out_12="កខគឃងចឆជឈញដឋឌឍណតថទធនបផពភមយរលវសហឡអឝឞ"; + this.s_v_gen_key_13=['','','','','','','','','','','','','','','','']; + this.s_v_gen_14="ាិីឹឺុូួើឿៀេែៃោៅ"; + this.s_v_pseudo_key_15=['','','']; + this.s_v_pseudo_16="ំះៈ"; + this.s_v_key_17=['','','','','','','','','','','','','','','','','','','']; + this.s_v_out_18="ាិីឹឺុូួើឿៀេែៃោៅំះៈ"; + this.s_v_any_19="ាិីឹឺុូួើឿៀេែៃោៅំះៈ"; + this.s_v_combo_R_20="េោុិីឹែ"; + this.s_v_combo_N_21="ាុ"; + this.s_v_combo_22="េោុិីឹែាុ"; + this.s_ind_v_key_23=['','','','','','','','','','','','','','','']; + this.s_ind_v_out_24="ឥឦឧឨឩឪឫឬឭឮឯឰឱឲឳ"; + this.s_diacritic_key_25=['','','','','','','','','','','']; + this.s_diacritic_out_26="់័៌៏៍ៈ៎៑៝ៜ្"; + this.s_c_shifter_key_27=['','']; + this.s_c_shifter_28="៉៊"; + this.s_punct_key_29=['','','','','','','','']; + this.s_punct_out_30="។៕៖ៗ៘៙៚៓"; + this.s_latin_punct_key_31=['','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','']; + this.s_latin_punct_out_32="«»()!\"%=?{}\\@*,×./[]‍‌+-÷:≈‘’;<>#&"; + this.s_spaces_key_33=['','','']; + this.s_spaces_out_34="​  "; + this.s_currency_key_35=['','','']; + this.s_currency_out_36="៛$€"; + this.s_digit_key_37=['','','','','','','','','','']; + this.s_digit_out_38="០១២៣៤៥៦៧៨៩"; + this.s_lek_attak_key_39=['','','','','','','','','','']; + this.s_lek_attak_out_40="៰៱៲៳៴៵៶៷៸៹"; + this.s_lunar_date_key_41=['','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','']; + this.s_lunar_date_out_42="᧬᧻᧹᧮᧢᧯᧰᧱᧧᧲᧳᧴᧽᧼᧨᧩᧠᧣᧭᧤᧦᧺᧡᧸᧥᧷᧵᧾᧿᧪᧫᧶"; + this.s_input_subcons_43=['','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','','']; + this.s_subcons_44="កខគឃងចឆជឈញដឋឌឍណតថទធនបផពភមយរលវឝឞសហឡអ"; + this.s_arabic_digit_key_45=['','','','','','','','','','']; + this.s_arabic_digit_out_46="0123456789"; + this.s_v_above_47="ិីឹឺើ័"; + this.s_shiftable_c_1st_48="សហអ"; + this.s_shiftable_BA_49="ប"; + this.s_shiftable_c_2nd_50="ងញមយរវនល"; + this.s_shiftable_c_2nd_with_BA_51="ងញមយរវនលប"; + this.s_c_2nd_combo_LO_52="យមងបវ"; + this.s_c_2nd_combo_MO_53="យលងរ"; + this.s_c_1st_combo_LO_54="បហអ"; + this.s_c_1st_combo_MO_55="ហសអ"; + this.s_c_combo_SA_56="បយលមនញងរវអ"; + this.s_c_combo_QA_57="ឆឈបផតទ"; + this.s_c_combo_HA_58="វឣ"; + this.s62="touch"; + this.KVS=[]; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.gs=function(t,e) { + return this.g_main_0(t,e); + }; + this.g_main_0=function(t,e) { + var k=KeymanWeb,r=0,m=0; + if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKSP /* 0x08 */)) { + if(k.KFCM(2,t,['្',{t:'a',a:this.s_c_out_12}])&&k.KIFS(31,this.s62,t)){ + r=m=1; // Line 266 + k.KDC(2,t); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_combo_N_21},'ំ'])){ + r=m=1; // Line 229 + k.KDC(2,t); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_combo_R_20},'ះ'])){ + r=m=1; // Line 230 + k.KDC(2,t); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឞ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_K /* 0x4B */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឝ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_QUOTE /* 0xDE */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ៈ"); + } + else if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"ៈ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឯ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឦ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_O /* 0x4F */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឱ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_P /* 0x50 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឰ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_R /* 0x52 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឫ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_T /* 0x54 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឨ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_LBRKT /* 0xDB */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឩ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_RBRKT /* 0xDD */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឳ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៑"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_Q /* 0x51 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"ៜ"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_W /* 0x57 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៝"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_EQUAL /* 0xBB */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៎"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៙"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៚"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_L /* 0x4C */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៘"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_M /* 0x4D */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៓"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_COLON /* 0xBA */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៖"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"}"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"‌"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"@"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"*"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"{"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"+"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"#"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"×"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"÷"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,":"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_H /* 0x48 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"‘"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"’"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_N /* 0x4E */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,";"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_S /* 0x53 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"-"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_U /* 0x55 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"]"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_V /* 0x56 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"&"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_X /* 0x58 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,">"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"["); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_Z /* 0x5A */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"<"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_COMMA /* 0xBC */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,","); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_HYPHEN /* 0xBD */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"≈"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_PERIOD /* 0xBE */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"."); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_SLASH /* 0xBF */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"/"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_BKQUOTE /* 0xC0 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"‍"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_BKSLASH /* 0xDC */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"\\"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 195 + k.KDC(0,t); + k.KO(-1,t,"$"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 195 + k.KDC(0,t); + k.KO(-1,t,"€"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៰"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៱"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៲"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៳"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៴"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៵"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៶"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៷"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៸"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 197 + k.KDC(0,t); + k.KO(-1,t,"៹"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧬"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧻"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧹"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧮"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧢"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧯"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧰"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_H /* 0x48 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧱"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧧"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧲"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_K /* 0x4B */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧳"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_L /* 0x4C */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧴"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_M /* 0x4D */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧽"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_N /* 0x4E */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧼"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_O /* 0x4F */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧨"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_P /* 0x50 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧩"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_Q /* 0x51 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧠"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_R /* 0x52 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧣"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_S /* 0x53 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧭"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_T /* 0x54 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧤"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_U /* 0x55 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧦"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_V /* 0x56 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧺"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_W /* 0x57 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧡"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_X /* 0x58 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧸"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧥"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_Z /* 0x5A */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧷"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_COLON /* 0xBA */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧵"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_COMMA /* 0xBC */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧾"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_PERIOD /* 0xBE */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧿"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_LBRKT /* 0xDB */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧪"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_RBRKT /* 0xDD */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧫"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4018 */, keyCodes.K_QUOTE /* 0xDE */)) { + if(1){ + r=m=1; // Line 198 + k.KDC(0,t); + k.KO(-1,t,"᧶"); + } + } + else if(k.KKM(e, modCodes.RALT | modCodes.VIRTUAL_KEY /* 0x4008 */, keyCodes.K_SPACE /* 0x20 */)) { + if(1){ + r=m=1; // Line 199 + k.KDC(0,t); + k.KO(-1,t," "); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x100)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ក"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x101)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ខ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x102)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្គ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x103)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឃ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x104)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ង"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x105)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ច"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x106)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឆ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x107)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ជ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x108)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឈ"); + } + } + if(m) {} + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x109)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ញ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10A)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ដ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10B)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឋ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10C)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឌ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10D)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឍ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10E)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ណ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x10F)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ត"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x110)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ថ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x111)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ទ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x112)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ធ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x113)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ន"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x114)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ប"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x115)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ផ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x116)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ព"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x117)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ភ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x118)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ម"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x119)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្យ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11A)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្រ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11B)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ល"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11C)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្វ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11D)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឝ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11E)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឞ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x11F)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ស"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x120)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ហ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x121)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្ឡ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, 0x122)) { + if(1){ + r=m=1; // Line 262 + k.KDC(0,t); + k.KO(-1,t,"្អ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPSTAR /* 0x6A */)) { + if(1){ + r=m=1; // Line 268 + k.KDC(0,t); + k.KO(-1,t,"*"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPSTAR /* 0x6A */)) { + if(1){ + r=m=1; // Line 269 + k.KDC(0,t); + k.KO(-1,t,"*"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPPLUS /* 0x6B */)) { + if(1){ + r=m=1; // Line 270 + k.KDC(0,t); + k.KO(-1,t,"+"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPPLUS /* 0x6B */)) { + if(1){ + r=m=1; // Line 271 + k.KDC(0,t); + k.KO(-1,t,"+"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPMINUS /* 0x6D */)) { + if(1){ + r=m=1; // Line 272 + k.KDC(0,t); + k.KO(-1,t,"-"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPMINUS /* 0x6D */)) { + if(1){ + r=m=1; // Line 273 + k.KDC(0,t); + k.KO(-1,t,"-"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPDOT /* 0x6E */)) { + if(1){ + r=m=1; // Line 274 + k.KDC(0,t); + k.KO(-1,t,"."); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPDOT /* 0x6E */)) { + if(1){ + r=m=1; // Line 275 + k.KDC(0,t); + k.KO(-1,t,"."); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_NPSLASH /* 0x6F */)) { + if(1){ + r=m=1; // Line 276 + k.KDC(0,t); + k.KO(-1,t,"/"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_NPSLASH /* 0x6F */)) { + if(1){ + r=m=1; // Line 277 + k.KDC(0,t); + k.KO(-1,t,"/"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_SPACE /* 0x20 */)) { + if(k.KFCM(1,t,['​'])){ + r=m=1; // Line 225 + k.KDC(1,t); + k.KO(-1,t," "); + } + else if(1){ + r=m=1; // Line 199 + k.KDC(0,t); + k.KO(-1,t,"​"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_SPACE /* 0x20 */)) { + if(1){ + r=m=1; // Line 199 + k.KDC(0,t); + k.KO(-1,t," "); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"!"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_QUOTE /* 0xDE */)) { + if(k.KFCM(3,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ'])){ + r=m=1; // Line 244 + k.KDC(3,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្អ៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54}])){ + r=m=1; // Line 245 + k.KDC(3,t); + k.KO(-1,t,"ល្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55}])){ + r=m=1; // Line 246 + k.KDC(3,t); + k.KO(-1,t,"ម្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56}])){ + r=m=1; // Line 247 + k.KDC(3,t); + k.KO(-1,t,"ស្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៉"); + k.KB(t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ'])){ + r=m=1; // Line 248 + k.KDC(3,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្ហ៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['អ','្','ង'])){ + r=m=1; // Line 249 + k.KDC(3,t); + k.KO(-1,t,"អ្ង៉"); + k.KB(t); + } + else if(k.KFCM(3,t,['អ','្','វ'])){ + r=m=1; // Line 250 + k.KDC(3,t); + k.KO(-1,t,"អ្វ៉"); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_c_shifter_28}])){ + r=m=1; // Line 215 + k.KDC(1,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_shiftable_c_1st_48}])){ + r=m=1; // Line 239 + k.KDC(1,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៉"); + k.KB(t); + } + else if(1){ + r=m=1; // Line 192 + k.KDC(0,t); + k.KO(-1,t,"៉"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"\""); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 195 + k.KDC(0,t); + k.KO(-1,t,"៛"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"%"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"័"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_QUOTE /* 0xDE */)) { + if(k.KFCM(2,t,['្',{t:'a',a:this.s_c_out_12}])){ + r=m=1; // Line 214 + k.KDC(2,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_out_12,2,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_v_gen_14}])){ + r=m=1; // Line 211 + k.KDC(1,t); + k.KIO(-1,this.s_v_gen_14,1,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_v_pseudo_16}])){ + r=m=1; // Line 212 + k.KDC(1,t); + k.KIO(-1,this.s_v_pseudo_16,1,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_c_shifter_28}])){ + r=m=1; // Line 213 + k.KDC(1,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KB(t); + } + else if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"់"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"("); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,")"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៏"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_EQUAL /* 0xBB */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"="); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_COMMA /* 0xBC */)) { + if(1){ + r=m=1; // Line 206 + k.KDC(0,t); + k.KO(-1,t,"ុំ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_HYPHEN /* 0xBD */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឥ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_PERIOD /* 0xBE */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"។"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_SLASH /* 0xBF */)) { + if(k.KFCM(3,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52}])){ + r=m=1; // Line 254 + k.KDC(3,t); + k.KO(-1,t,"ល្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៊"); + k.KB(t); + } + else if(k.KFCM(3,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53}])){ + r=m=1; // Line 255 + k.KDC(3,t); + k.KO(-1,t,"ម្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៊"); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_c_shifter_28}])){ + r=m=1; // Line 215 + k.KDC(1,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KB(t); + } + else if(k.KFCM(1,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51}])){ + r=m=1; // Line 240 + k.KDC(1,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៊"); + k.KB(t); + } + else if(1){ + r=m=1; // Line 192 + k.KDC(0,t); + k.KO(-1,t,"៊"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_0 /* 0x30 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"០"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_1 /* 0x31 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"១"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"២"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_3 /* 0x33 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៣"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_4 /* 0x34 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៤"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_5 /* 0x35 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៥"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៦"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_7 /* 0x37 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៧"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_8 /* 0x38 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៨"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_9 /* 0x39 */)) { + if(1){ + r=m=1; // Line 196 + k.KDC(0,t); + k.KO(-1,t,"៩"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_COLON /* 0xBA */)) { + if(1){ + r=m=1; // Line 205 + k.KDC(0,t); + k.KO(-1,t,"ោះ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_COLON /* 0xBA */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ើ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_COMMA /* 0xBC */)) { + if(1){ + r=m=1; // Line 207 + k.KDC(0,t); + k.KO(-1,t,"ុះ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_EQUAL /* 0xBB */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឲ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_PERIOD /* 0xBE */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"៕"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_SLASH /* 0xBF */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"?"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_2 /* 0x32 */)) { + if(1){ + r=m=1; // Line 193 + k.KDC(0,t); + k.KO(-1,t,"ៗ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 203 + k.KDC(0,t); + k.KO(-1,t,"ាំ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ព"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ជ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឌ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ែ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ធ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"អ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_H /* 0x48 */)) { + if(k.KFCM(1,t,['ះ'])){ + r=m=1; // Line 219 + k.KDC(1,t); + k.KO(-1,t,"ៈ"); + } + else if(k.KFCM(1,t,['ៈ'])){ + r=m=1; // Line 220 + k.KDC(1,t); + k.KO(-1,t,"ះ"); + } + else if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ះ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ី"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ញ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_K /* 0x4B */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"គ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_L /* 0x4C */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឡ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_M /* 0x4D */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ំ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_N /* 0x4E */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ណ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_O /* 0x4F */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ៅ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_P /* 0x50 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ភ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_Q /* 0x51 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឈ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_R /* 0x52 */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឬ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_S /* 0x53 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ៃ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_T /* 0x54 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ទ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_U /* 0x55 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ូ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_V /* 0x56 */)) { + if(1){ + r=m=1; // Line 204 + k.KDC(0,t); + k.KO(-1,t,"េះ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_W /* 0x57 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ឺ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_X /* 0x58 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឃ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ួ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_Z /* 0x5A */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឍ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_LBRKT /* 0xDB */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ៀ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKSLASH /* 0xDC */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឮ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_RBRKT /* 0xDD */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឪ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_6 /* 0x36 */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៍"); + } + } + if(m) {} + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_HYPHEN /* 0xBD */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"៌"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_BKQUOTE /* 0xC0 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"«"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_A /* 0x41 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ា"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_B /* 0x42 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ប"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_C /* 0x43 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ច"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_D /* 0x44 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ដ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_E /* 0x45 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"េ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_F /* 0x46 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ថ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_G /* 0x47 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ង"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_H /* 0x48 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ហ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_I /* 0x49 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ិ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_J /* 0x4A */)) { + if(1){ + r=m=1; // Line 191 + k.KDC(0,t); + k.KO(-1,t,"្"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_K /* 0x4B */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ក"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_L /* 0x4C */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ល"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_M /* 0x4D */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ម"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_N /* 0x4E */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ន"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_O /* 0x4F */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ោ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_P /* 0x50 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ផ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Q /* 0x51 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឆ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_R /* 0x52 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"រ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_S /* 0x53 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ស"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_T /* 0x54 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ត"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_U /* 0x55 */)) { + if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ា','ំ'])){ + r=m=1; // Line 234 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ា','ំ'])){ + r=m=1; // Line 235 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ុ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_V /* 0x56 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"វ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_W /* 0x57 */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ឹ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_X /* 0x58 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ខ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Y /* 0x59 */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"យ"); + } + } + else if(k.KKM(e, modCodes.VIRTUAL_KEY /* 0x4000 */, keyCodes.K_Z /* 0x5A */)) { + if(1){ + r=m=1; // Line 188 + k.KDC(0,t); + k.KO(-1,t,"ឋ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_LBRKT /* 0xDB */)) { + if(1){ + r=m=1; // Line 189 + k.KDC(0,t); + k.KO(-1,t,"ឿ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_BKSLASH /* 0xDC */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឭ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_RBRKT /* 0xDD */)) { + if(1){ + r=m=1; // Line 190 + k.KDC(0,t); + k.KO(-1,t,"ឧ"); + } + } + else if(k.KKM(e, modCodes.SHIFT | modCodes.VIRTUAL_KEY /* 0x4010 */, keyCodes.K_BKQUOTE /* 0xC0 */)) { + if(1){ + r=m=1; // Line 194 + k.KDC(0,t); + k.KO(-1,t,"»"); + } + } + if(m==1) { + + k.KDC(-1,t); + r=this.g_normalise_1(t,e); + m=2; + } + return r; + }; + this.g_normalise_1=function(t,e) { + var k=KeymanWeb,r=1,m=0; + if(k.KFCM(7,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ','ំ','ា','ំ'])){ + m=1; // Line 376 + k.KDC(7,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ','ំ','ា','ំ'])){ + m=1; // Line 381 + k.KDC(7,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ','ំ','ា','ំ'])){ + m=1; // Line 386 + k.KDC(7,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ស','្','ប','ុ','ំ','ា','ំ'])){ + m=1; // Line 391 + k.KDC(7,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ','ំ','ា','ំ'])){ + m=1; // Line 396 + k.KDC(7,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ','ំ','ា','ំ'])){ + m=1; // Line 401 + k.KDC(7,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['អ','្','ង','ុ','ំ','ា','ំ'])){ + m=1; // Line 406 + k.KDC(7,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['អ','្','វ','ុ','ំ','ា','ំ'])){ + m=1; // Line 411 + k.KDC(7,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ហ','្','ប','ុ','ំ','ា','ំ'])){ + m=1; // Line 416 + k.KDC(7,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ហ','្',{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ំ','ា','ំ'])){ + m=1; // Line 422 + k.KDC(7,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ','ំ','ា','ំ'])){ + m=1; // Line 429 + k.KDC(7,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(7,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ','ំ','ា','ំ'])){ + m=1; // Line 434 + k.KDC(7,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['្','ដ',{t:'a',a:this.s_v_combo_N_21},'ំ','្','រ'])){ + m=1; // Line 340 + k.KDC(6,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_N_21,3,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['្','ដ',{t:'a',a:this.s_v_combo_R_20},'ះ','្','រ'])){ + m=1; // Line 341 + k.KDC(6,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_R_20,3,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(6,t,['្','រ',{t:'a',a:this.s_v_combo_N_21},'ំ','្','ដ'])){ + m=1; // Line 344 + k.KDC(6,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_N_21,3,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['្','រ',{t:'a',a:this.s_v_combo_R_20},'ះ','្','ដ'])){ + m=1; // Line 345 + k.KDC(6,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_R_20,3,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(6,t,['្','រ',{t:'a',a:this.s_v_combo_N_21},'ំ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 350 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,6,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_N_21,3,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['្','រ',{t:'a',a:this.s_v_combo_R_20},'ះ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 351 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,6,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_combo_R_20,3,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ','ា','ំ'])){ + m=1; // Line 374 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ','ា','ំ'])){ + m=1; // Line 379 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ','ា','ំ'])){ + m=1; // Line 384 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្','ប','ុ','ា','ំ'])){ + m=1; // Line 389 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ','ា','ំ'])){ + m=1; // Line 394 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ','ា','ំ'])){ + m=1; // Line 399 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','ង','ុ','ា','ំ'])){ + m=1; // Line 404 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','វ','ុ','ា','ំ'])){ + m=1; // Line 409 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ហ','្','ប','ុ','ា','ំ'])){ + m=1; // Line 414 + k.KDC(6,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ប"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ហ','្',{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ា','ំ'])){ + m=1; // Line 420 + k.KDC(6,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ','ា','ំ'])){ + m=1; // Line 427 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ','ា','ំ'])){ + m=1; // Line 432 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'៊',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 454 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_gen_14,5,t); + k.KIO(-1,this.s_v_pseudo_16,6,t); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'៊',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 455 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_gen_14,5,t); + k.KIO(-1,this.s_v_pseudo_16,6,t); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','៉','ា','ំ'])){ + m=1; // Line 489 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'៉','ា','ំ'])){ + m=1; // Line 490 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'៉','ា','ំ'])){ + m=1; // Line 491 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្','ប','៉','ា','ំ'])){ + m=1; // Line 492 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'៉','ា','ំ'])){ + m=1; // Line 493 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','៉','ា','ំ'])){ + m=1; // Line 494 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','ង','៉','ា','ំ'])){ + m=1; // Line 495 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','វ','៉','ា','ំ'])){ + m=1; // Line 496 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ា','ុ','ំ'])){ + m=1; // Line 503 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ','ំ','ា'])){ + m=1; // Line 504 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ា','ុ','ំ'])){ + m=1; // Line 506 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ','ំ','ា'])){ + m=1; // Line 507 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ា','ុ','ំ'])){ + m=1; // Line 509 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ','ំ','ា'])){ + m=1; // Line 510 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ា','ុ','ំ'])){ + m=1; // Line 512 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ','ំ','ា'])){ + m=1; // Line 513 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ា','ុ','ំ'])){ + m=1; // Line 515 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ','ំ','ា'])){ + m=1; // Line 516 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','ង','ា','ុ','ំ'])){ + m=1; // Line 518 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','ង','ុ','ំ','ា'])){ + m=1; // Line 519 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','វ','ា','ុ','ំ'])){ + m=1; // Line 521 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['អ','្','វ','ុ','ំ','ា'])){ + m=1; // Line 522 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KO(-1,t,"ុ"); + k.KO(-1,t,"ា"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ា','ុ','ំ'])){ + m=1; // Line 529 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ','ំ','ា'])){ + m=1; // Line 530 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ា','ុ','ំ'])){ + m=1; // Line 532 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ','ំ','ា'])){ + m=1; // Line 533 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','េ','ុ','ី'])){ + m=1; // Line 541 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ','េ','ី'])){ + m=1; // Line 542 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','៉','េ','ី'])){ + m=1; // Line 543 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'េ','ុ','ី'])){ + m=1; // Line 545 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ','េ','ី'])){ + m=1; // Line 546 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'៉','េ','ី'])){ + m=1; // Line 547 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'េ','ុ','ី'])){ + m=1; // Line 549 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ','េ','ី'])){ + m=1; // Line 550 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'៉','េ','ី'])){ + m=1; // Line 551 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'េ','ុ','ី'])){ + m=1; // Line 553 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ','េ','ី'])){ + m=1; // Line 554 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'៉','េ','ី'])){ + m=1; // Line 555 + k.KDC(6,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','េ','ុ','ី'])){ + m=1; // Line 557 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ','េ','ី'])){ + m=1; // Line 558 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊ើ"); + } + else if(k.KFCM(6,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','៉','េ','ី'])){ + m=1; // Line 559 + k.KDC(6,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','ង','េ','ុ','ី'])){ + m=1; // Line 561 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','ង','ុ','េ','ី'])){ + m=1; // Line 562 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','ង','៉','េ','ី'])){ + m=1; // Line 563 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','វ','េ','ុ','ី'])){ + m=1; // Line 565 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','វ','ុ','េ','ី'])){ + m=1; // Line 566 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊ើ"); + } + else if(k.KFCM(6,t,['អ','្','វ','៉','េ','ី'])){ + m=1; // Line 567 + k.KDC(6,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'េ','ុ','ី'])){ + m=1; // Line 575 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ','េ','ី'])){ + m=1; // Line 576 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'៊','េ','ី'])){ + m=1; // Line 577 + k.KDC(6,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'េ','ុ','ី'])){ + m=1; // Line 579 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ','េ','ី'])){ + m=1; // Line 580 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'៊','េ','ី'])){ + m=1; // Line 581 + k.KDC(6,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(6,t,['្','យ','្',{t:'a',a:this.s_c_out_12},'េ','ឺ'])){ + m=1; // Line 631 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_out_12,4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(6,t,['្','យ','្',{t:'a',a:this.s_c_out_12},'េ','ឹ'])){ + m=1; // Line 632 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_out_12,4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(6,t,['្','យ','្',{t:'a',a:this.s_c_out_12},'េ','ី'])){ + m=1; // Line 633 + k.KDC(6,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_out_12,4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_combo_N_21},'ំ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 331 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,5,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KIO(-1,this.s_v_combo_N_21,2,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_combo_R_20},'ះ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 332 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,5,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KIO(-1,this.s_v_combo_R_20,2,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(5,t,['្','ដ',{t:'a',a:this.s_v_any_19},'្','រ'])){ + m=1; // Line 339 + k.KDC(5,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_any_19,3,t); + } + else if(k.KFCM(5,t,['្','រ',{t:'a',a:this.s_v_any_19},'្','ដ'])){ + m=1; // Line 343 + k.KDC(5,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_any_19,3,t); + } + else if(k.KFCM(5,t,['្','រ',{t:'a',a:this.s_c_shifter_28},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 347 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,5,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_c_shifter_28,3,t); + } + else if(k.KFCM(5,t,['្','រ',{t:'a',a:this.s_v_any_19},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 349 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,5,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + k.KIO(-1,this.s_v_any_19,3,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 373 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 375 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 378 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 380 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 383 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 385 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + if(m) {} + else if(k.KFCM(5,t,['ស','្','ប','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 388 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ស','្','ប',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 390 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 393 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 395 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 398 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 400 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['អ','្','ង','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 403 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['អ','្','ង',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 405 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['អ','្','វ','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 408 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['អ','្','វ',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 410 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ហ','្','ប','ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 413 + k.KDC(5,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ហ','្','ប',{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 415 + k.KDC(5,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ហ','្',{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 419 + k.KDC(5,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ហ','្',{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 421 + k.KDC(5,t); + k.KO(-1,t,"ហ"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 426 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 428 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 431 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 433 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ','ំ','ា','ំ'])){ + m=1; // Line 441 + k.KDC(5,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ំ','ា','ំ'])){ + m=1; // Line 448 + k.KDC(5,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_2nd_combo_LO_52},'៊',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 452 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_LO_52,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_2nd_combo_MO_53},'៊',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 453 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_2nd_combo_MO_53,3,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['្',{t:'a',a:this.s_shiftable_c_2nd_50},'៊',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 463 + k.KDC(5,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_50,2,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_gen_14,4,t); + k.KIO(-1,this.s_v_pseudo_16,5,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_QA_57},'្','អ','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 481 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_QA_57,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"អ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ល','្',{t:'a',a:this.s_c_1st_combo_LO_54},'៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 482 + k.KDC(5,t); + k.KO(-1,t,"ល"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_LO_54,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ម','្',{t:'a',a:this.s_c_1st_combo_MO_55},'៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 483 + k.KDC(5,t); + k.KO(-1,t,"ម"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_1st_combo_MO_55,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ស','្','ប','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 484 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ប៉"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ស','្',{t:'a',a:this.s_c_combo_SA_56},'៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 485 + k.KDC(5,t); + k.KO(-1,t,"ស"); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_c_combo_SA_56,3,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,[{t:'a',a:this.s_c_combo_HA_58},'្','ហ','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 486 + k.KDC(5,t); + k.KIO(-1,this.s_c_combo_HA_58,1,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"ហ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['អ','្','ង','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 487 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"ង៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['អ','្','វ','៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 488 + k.KDC(5,t); + k.KO(-1,t,"អ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វ៊"); + k.KIO(-1,this.s_v_above_47,5,t); + } + else if(k.KFCM(5,t,['ព','័','ន','្','ឋ'])){ + m=1; // Line 619 + k.KDC(5,t); + k.KO(-1,t,"ព"); + k.KO(-1,t,"័"); + k.KO(-1,t,"ន"); + k.KO(-1,t,"្ធ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 312 + k.KDC(4,t); + k.KIO(-1,this.s_v_gen_14,3,t); + k.KIO(-1,this.s_v_pseudo_16,4,t); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_v_combo_N_21},'ំ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 325 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,4,t); + k.KIO(-1,this.s_v_combo_N_21,1,t); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_v_combo_R_20},'ះ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 326 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,4,t); + k.KIO(-1,this.s_v_combo_R_20,1,t); + k.KO(-1,t,"ះ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_any_19},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 330 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,4,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + k.KIO(-1,this.s_v_any_19,2,t); + } + else if(k.KFCM(4,t,['្','ដ','្','រ'])){ + m=1; // Line 336 + k.KDC(4,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + } + else if(k.KFCM(4,t,['្','រ','្','ដ'])){ + m=1; // Line 337 + k.KDC(4,t); + k.KO(-1,t,"្ត"); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + } + else if(k.KFCM(4,t,['្','រ','្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 348 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,4,t); + k.KO(-1,t,"្"); + k.KO(-1,t,"រ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 362 + k.KDC(4,t); + k.KIO(-1,this.s_v_gen_14,2,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ','ា','ំ'])){ + m=1; // Line 439 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ា','ំ'])){ + m=1; // Line 446 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'៊',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 460 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_gen_14,3,t); + k.KIO(-1,this.s_v_pseudo_16,4,t); + } + else if(k.KFCM(4,t,['្',{t:'a',a:this.s_shiftable_c_2nd_50},'៊',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 462 + k.KDC(4,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_shiftable_c_2nd_50,2,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,4,t); + } + else if(k.KFCM(4,t,['ប','្','យ',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 467 + k.KDC(4,t); + k.KO(-1,t,"ប្យ"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ស','្','ប',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 468 + k.KDC(4,t); + k.KO(-1,t,"ស្ប"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ឆ','្','ប',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 469 + k.KDC(4,t); + k.KO(-1,t,"ឆ្ប"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ប','្','យ',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 470 + k.KDC(4,t); + k.KO(-1,t,"ប្យ"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ស','្','ប',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 471 + k.KDC(4,t); + k.KO(-1,t,"ស្ប"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,['ឆ','្','ប',{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 472 + k.KDC(4,t); + k.KO(-1,t,"ឆ្ប"); + k.KIO(-1,this.s_c_shifter_28,4,t); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'៉',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 477 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_gen_14,3,t); + k.KIO(-1,this.s_v_pseudo_16,4,t); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ា','ុ','ំ'])){ + m=1; // Line 500 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ','ំ','ា'])){ + m=1; // Line 501 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ា','ុ','ំ'])){ + m=1; // Line 526 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ','ំ','ា'])){ + m=1; // Line 527 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KO(-1,t,"ា"); + k.KO(-1,t,"ំ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'េ','ុ','ី'])){ + m=1; // Line 537 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ','េ','ី'])){ + m=1; // Line 538 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_1st_48},'៉','េ','ី'])){ + m=1; // Line 539 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'េ','ុ','ី'])){ + m=1; // Line 571 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'ុ','េ','ី'])){ + m=1; // Line 572 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(4,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'៊','េ','ី'])){ + m=1; // Line 573 + k.KDC(4,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉ើ"); + } + else if(k.KFCM(4,t,['ព','ន','្','ឋ'])){ + m=1; // Line 618 + k.KDC(4,t); + k.KO(-1,t,"ព"); + k.KO(-1,t,"ន"); + k.KO(-1,t,"្ធ"); + } + else if(k.KFCM(4,t,['្','យ','េ','ឺ'])){ + m=1; // Line 627 + k.KDC(4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(4,t,['្','យ','េ','ឹ'])){ + m=1; // Line 628 + k.KDC(4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(4,t,['្','យ','េ','ី'])){ + m=1; // Line 629 + k.KDC(4,t); + k.KO(-1,t,"ឿ"); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_gen_14}])){ + m=1; // Line 308 + k.KDC(3,t); + k.KIO(-1,this.s_v_gen_14,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 309 + k.KDC(3,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 310 + k.KDC(3,t); + k.KIO(-1,this.s_v_gen_14,2,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 311 + k.KDC(3,t); + k.KIO(-1,this.s_v_gen_14,2,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + } + else if(k.KFCM(3,t,['្',{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 320 + k.KDC(3,t); + k.KIO(-1,this.s_v_gen_14,2,t); + k.KIO(-1,this.s_v_pseudo_16,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_any_19},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 324 + k.KDC(3,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,3,t); + k.KIO(-1,this.s_v_any_19,1,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_c_shifter_28},'្',{t:'a',a:this.s_subcons_44}])){ + m=1; // Line 355 + k.KDC(3,t); + k.KO(-1,t,"្"); + k.KIO(-1,this.s_subcons_44,3,t); + k.KIO(-1,this.s_c_shifter_28,1,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 360 + k.KDC(3,t); + k.KIO(-1,this.s_c_shifter_28,3,t); + k.KIO(-1,this.s_v_gen_14,1,t); + k.KIO(-1,this.s_v_pseudo_16,2,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_c_shifter_28},{t:'a',a:this.s_v_any_19},{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 361 + k.KDC(3,t); + k.KIO(-1,this.s_c_shifter_28,3,t); + k.KIO(-1,this.s_v_any_19,2,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_1st_48},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 438 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_1st_48},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 440 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,2,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},'ុ',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 445 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_2nd_with_BA_51},{t:'a',a:this.s_v_above_47},'ុ'])){ + m=1; // Line 447 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_2nd_with_BA_51,1,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,2,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_2nd_50},'៊',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 459 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_2nd_50,1,t); + k.KO(-1,t,"៉"); + k.KIO(-1,this.s_v_above_47,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_shiftable_c_1st_48},'៉',{t:'a',a:this.s_v_above_47}])){ + m=1; // Line 476 + k.KDC(3,t); + k.KIO(-1,this.s_shiftable_c_1st_48,1,t); + k.KO(-1,t,"៊"); + k.KIO(-1,this.s_v_above_47,3,t); + } + else if(k.KFCM(3,t,[{t:'a',a:this.s_c_out_12},{t:'a',a:this.s_v_gen_14},'៌'])){ + m=1; // Line 585 + k.KDC(3,t); + k.KIO(-1,this.s_c_out_12,1,t); + k.KO(-1,t,"៌"); + k.KIO(-1,this.s_v_gen_14,2,t); + } + else if(k.KFCM(3,t,['ណ','្','ត'])){ + m=1; // Line 589 + k.KDC(3,t); + k.KO(-1,t,"ណ"); + k.KO(-1,t,"្ដ"); + } + else if(k.KFCM(3,t,['ន','្','ដ'])){ + m=1; // Line 590 + k.KDC(3,t); + k.KO(-1,t,"ន"); + k.KO(-1,t,"្ត"); + } + else if(k.KFCM(3,t,['ទ','្','ប'])){ + m=1; // Line 594 + k.KDC(3,t); + k.KO(-1,t,"ឡ"); + } + else if(k.KFCM(3,t,['ប','្','ញ'])){ + m=1; // Line 596 + k.KDC(3,t); + k.KO(-1,t,"ឫ"); + } + else if(k.KFCM(3,t,['ព','្','ញ'])){ + m=1; // Line 602 + k.KDC(3,t); + k.KO(-1,t,"ឭ"); + } + else if(k.KFCM(3,t,['ព','្','ឋ'])){ + m=1; // Line 605 + k.KDC(3,t); + k.KO(-1,t,"ឰ"); + } + else if(k.KFCM(3,t,['ដ','្','ធ'])){ + m=1; // Line 613 + k.KDC(3,t); + k.KO(-1,t,"ដ្ឋ"); + } + else if(k.KFCM(3,t,['ទ','្','ឋ'])){ + m=1; // Line 614 + k.KDC(3,t); + k.KO(-1,t,"ទ្ធ"); + } + else if(k.KFCM(3,t,['ឪ','្','យ'])){ + m=1; // Line 622 + k.KDC(3,t); + k.KO(-1,t,"ឱ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"យ"); + } + else if(k.KFCM(3,t,['ឳ','្','យ'])){ + m=1; // Line 623 + k.KDC(3,t); + k.KO(-1,t,"ឱ"); + k.KO(-1,t,"្"); + k.KO(-1,t,"យ"); + } + else if(k.KFCM(3,t,['ញ','្','វ'])){ + m=1; // Line 625 + k.KDC(3,t); + k.KO(-1,t,"ព"); + k.KO(-1,t,"្"); + k.KO(-1,t,"វា"); + } + else if(k.KFCM(2,t,['េ','ា'])){ + m=1; // Line 291 + k.KDC(2,t); + k.KO(-1,t,"ោ"); + } + else if(k.KFCM(2,t,['ា','េ'])){ + m=1; // Line 292 + k.KDC(2,t); + k.KO(-1,t,"ោ"); + } + else if(k.KFCM(2,t,['េ','ី'])){ + m=1; // Line 293 + k.KDC(2,t); + k.KO(-1,t,"ើ"); + } + else if(k.KFCM(2,t,['ី','េ'])){ + m=1; // Line 294 + k.KDC(2,t); + k.KO(-1,t,"ើ"); + } + else if(k.KFCM(2,t,['ំ','ុ'])){ + m=1; // Line 298 + k.KDC(2,t); + k.KO(-1,t,"ុំ"); + } + else if(k.KFCM(2,t,['ំ','ា'])){ + m=1; // Line 299 + k.KDC(2,t); + k.KO(-1,t,"ាំ"); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_gen_14},{t:'a',a:this.s_v_gen_14}])){ + m=1; // Line 304 + k.KDC(2,t); + k.KIO(-1,this.s_v_gen_14,2,t); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_pseudo_16},{t:'a',a:this.s_v_pseudo_16}])){ + m=1; // Line 313 + k.KDC(2,t); + k.KIO(-1,this.s_v_pseudo_16,2,t); + } + if(m) {} + else if(k.KFCM(2,t,['្','្'])){ + m=1; // Line 318 + k.KDC(2,t); + k.KO(-1,t,"្"); + } + else if(k.KFCM(2,t,['្',{t:'a',a:this.s_v_any_19}])){ + m=1; // Line 319 + k.KDC(2,t); + k.KIO(-1,this.s_v_any_19,2,t); + } + else if(k.KFCM(2,t,[{t:'a',a:this.s_v_any_19},{t:'a',a:this.s_c_shifter_28}])){ + m=1; // Line 359 + k.KDC(2,t); + k.KIO(-1,this.s_c_shifter_28,2,t); + k.KIO(-1,this.s_v_any_19,1,t); + } + else if(k.KFCM(2,t,['ឫ','ុ'])){ + m=1; // Line 597 + k.KDC(2,t); + k.KO(-1,t,"ឬ"); + } + else if(k.KFCM(2,t,['ឭ','ា'])){ + m=1; // Line 599 + k.KDC(2,t); + k.KO(-1,t,"ញ"); + } + else if(k.KFCM(2,t,['ឮ','ា'])){ + m=1; // Line 600 + k.KDC(2,t); + k.KO(-1,t,"ញ"); + } + else if(k.KFCM(2,t,['ឭ','ុ'])){ + m=1; // Line 603 + k.KDC(2,t); + k.KO(-1,t,"ឮ"); + } + else if(k.KFCM(2,t,['ឧ','ិ'])){ + m=1; // Line 607 + k.KDC(2,t); + k.KO(-1,t,"ឱ"); + } + else if(k.KFCM(2,t,['ឧ','៌'])){ + m=1; // Line 608 + k.KDC(2,t); + k.KO(-1,t,"ឱ"); + } + else if(k.KFCM(2,t,['ឧ','៍'])){ + m=1; // Line 609 + k.KDC(2,t); + k.KO(-1,t,"ឱ"); + } + return r; + }; +} diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.keyman-touch-layout b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.keyman-touch-layout new file mode 100644 index 0000000000..711f849008 --- /dev/null +++ b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.keyman-touch-layout @@ -0,0 +1,1950 @@ +{ + "tablet": { + "displayUnderlying": false, + "layer": [ + { + "id": "default", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "១" + }, + { + "id": "K_2", + "text": "២" + }, + { + "id": "K_3", + "text": "៣" + }, + { + "id": "K_4", + "text": "៤" + }, + { + "id": "K_5", + "text": "៥" + }, + { + "id": "K_6", + "text": "៦" + }, + { + "id": "K_7", + "text": "៧" + }, + { + "id": "K_8", + "text": "៨" + }, + { + "id": "K_9", + "text": "៩" + }, + { + "id": "K_0", + "text": "០" + }, + { + "id": "K_HYPHEN", + "text": "ឥ" + }, + { + "id": "K_EQUAL", + "text": "ឲ" + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "100", + "sp": "1" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_Q", + "text": "ឆ", + "pad": "75" + }, + { + "id": "K_W", + "text": "" + }, + { + "id": "K_E", + "text": "" + }, + { + "id": "K_R", + "text": "រ" + }, + { + "id": "K_T", + "text": "ត" + }, + { + "id": "K_Y", + "text": "យ" + }, + { + "id": "K_U", + "text": "" + }, + { + "id": "K_I", + "text": "" + }, + { + "id": "K_O", + "text": "" + }, + { + "id": "K_P", + "text": "ផ" + }, + { + "id": "K_LBRKT", + "text": "" + }, + { + "id": "K_RBRKT", + "text": "ឪ" + }, + { + "id": "T_new_138", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_BKQUOTE", + "text": "«" + }, + { + "id": "K_A", + "text": "" + }, + { + "id": "K_S", + "text": "ស" + }, + { + "id": "K_D", + "text": "ដ" + }, + { + "id": "K_F", + "text": "ថ" + }, + { + "id": "K_G", + "text": "ង" + }, + { + "id": "K_H", + "text": "ហ" + }, + { + "id": "K_J", + "text": "" + }, + { + "id": "K_K", + "text": "ក" + }, + { + "id": "K_L", + "text": "ល" + }, + { + "id": "K_COLON", + "text": "" + }, + { + "id": "K_QUOTE", + "text": "" + }, + { + "id": "K_BKSLASH", + "text": "ឮ" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "width": "160", + "sp": "1", + "nextlayer": "shift" + }, + { + "id": "K_oE2", + "text": "" + }, + { + "id": "K_Z", + "text": "ឋ" + }, + { + "id": "K_X", + "text": "ខ" + }, + { + "id": "K_C", + "text": "ច" + }, + { + "id": "K_V", + "text": "វ" + }, + { + "id": "K_B", + "text": "ប" + }, + { + "id": "K_N", + "text": "ន" + }, + { + "id": "K_M", + "text": "ម" + }, + { + "id": "K_COMMA", + "text": "" + }, + { + "id": "K_PERIOD", + "text": "។" + }, + { + "id": "K_SLASH", + "text": "" + }, + { + "id": "T_new_164", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_LCONTROL", + "text": "*AltGr*", + "width": "160", + "sp": "1", + "nextlayer": "rightalt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "160", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": "​", + "width": "930" + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "160", + "sp": "1" + } + ] + } + ] + }, + { + "id": "rightalt", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "‌" + }, + { + "id": "K_2", + "text": "@" + }, + { + "id": "K_3", + "text": "" + }, + { + "id": "K_4", + "text": "$" + }, + { + "id": "K_5", + "text": "€" + }, + { + "id": "K_6", + "text": "៙" + }, + { + "id": "K_7", + "text": "៚" + }, + { + "id": "K_8", + "text": "*" + }, + { + "id": "K_9", + "text": "{" + }, + { + "id": "K_0", + "text": "}" + }, + { + "id": "K_HYPHEN", + "text": "≈" + }, + { + "id": "K_EQUAL", + "text": "" + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "100", + "sp": "1" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_Q", + "text": "ៜ", + "pad": "75" + }, + { + "id": "K_W", + "text": "" + }, + { + "id": "K_E", + "text": "ឯ" + }, + { + "id": "K_R", + "text": "ឫ" + }, + { + "id": "K_T", + "text": "ឨ" + }, + { + "id": "K_Y", + "text": "[" + }, + { + "id": "K_U", + "text": "]" + }, + { + "id": "K_I", + "text": "ឦ" + }, + { + "id": "K_O", + "text": "ឱ" + }, + { + "id": "K_P", + "text": "ឰ" + }, + { + "id": "K_LBRKT", + "text": "ឩ" + }, + { + "id": "K_RBRKT", + "text": "ឳ" + }, + { + "id": "T_new_307", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_BKQUOTE", + "text": "‍" + }, + { + "id": "K_A", + "text": "+" + }, + { + "id": "K_S", + "text": "-" + }, + { + "id": "K_D", + "text": "×" + }, + { + "id": "K_F", + "text": "÷" + }, + { + "id": "K_G", + "text": ":" + }, + { + "id": "K_H", + "text": "‘" + }, + { + "id": "K_J", + "text": "’" + }, + { + "id": "K_K", + "text": "ឝ" + }, + { + "id": "K_L", + "text": "៘" + }, + { + "id": "K_COLON", + "text": "៖" + }, + { + "id": "K_QUOTE", + "text": "ៈ" + }, + { + "id": "K_BKSLASH", + "text": "\\" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "width": "160", + "sp": "1", + "nextlayer": "shift" + }, + { + "id": "K_oE2", + "text": "" + }, + { + "id": "K_Z", + "text": "<" + }, + { + "id": "K_X", + "text": ">" + }, + { + "id": "K_C", + "text": "#" + }, + { + "id": "K_V", + "text": "&" + }, + { + "id": "K_B", + "text": "ឞ" + }, + { + "id": "K_N", + "text": ";" + }, + { + "id": "K_M", + "text": "" + }, + { + "id": "K_COMMA", + "text": "," + }, + { + "id": "K_PERIOD", + "text": "." + }, + { + "id": "K_SLASH", + "text": "/" + }, + { + "id": "T_new_333", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_LCONTROL", + "text": "*AltGr*", + "width": "160", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "160", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": " ", + "width": "930" + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "160", + "sp": "1" + } + ] + } + ] + }, + { + "id": "shift", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "!" + }, + { + "id": "K_2", + "text": "ៗ" + }, + { + "id": "K_3", + "text": "\"" + }, + { + "id": "K_4", + "text": "៛" + }, + { + "id": "K_5", + "text": "%" + }, + { + "id": "K_6", + "text": "" + }, + { + "id": "K_7", + "text": "" + }, + { + "id": "K_8", + "text": "" + }, + { + "id": "K_9", + "text": "(" + }, + { + "id": "K_0", + "text": ")" + }, + { + "id": "K_HYPHEN", + "text": "" + }, + { + "id": "K_EQUAL", + "text": "=" + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "100", + "sp": "1" + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_Q", + "text": "ឈ", + "pad": "75" + }, + { + "id": "K_W", + "text": "" + }, + { + "id": "K_E", + "text": "" + }, + { + "id": "K_R", + "text": "ឬ" + }, + { + "id": "K_T", + "text": "ទ" + }, + { + "id": "K_Y", + "text": "" + }, + { + "id": "K_U", + "text": "" + }, + { + "id": "K_I", + "text": "" + }, + { + "id": "K_O", + "text": "" + }, + { + "id": "K_P", + "text": "ភ" + }, + { + "id": "K_LBRKT", + "text": "" + }, + { + "id": "K_RBRKT", + "text": "ឧ" + }, + { + "id": "T_new_364", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_BKQUOTE", + "text": "»" + }, + { + "id": "K_A", + "text": "" + }, + { + "id": "K_S", + "text": "" + }, + { + "id": "K_D", + "text": "ឌ" + }, + { + "id": "K_F", + "text": "ធ" + }, + { + "id": "K_G", + "text": "អ" + }, + { + "id": "K_H", + "text": "ះ" + }, + { + "id": "K_J", + "text": "ញ" + }, + { + "id": "K_K", + "text": "គ" + }, + { + "id": "K_L", + "text": "ឡ" + }, + { + "id": "K_COLON", + "text": "" + }, + { + "id": "K_QUOTE", + "text": "" + }, + { + "id": "K_BKSLASH", + "text": "ឭ" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_SHIFT", + "text": "*Shift*", + "width": "160", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_oE2", + "text": "" + }, + { + "id": "K_Z", + "text": "ឍ" + }, + { + "id": "K_X", + "text": "ឃ" + }, + { + "id": "K_C", + "text": "ជ" + }, + { + "id": "K_V", + "text": "" + }, + { + "id": "K_B", + "text": "ព" + }, + { + "id": "K_N", + "text": "ណ" + }, + { + "id": "K_M", + "text": "" + }, + { + "id": "K_COMMA", + "text": "" + }, + { + "id": "K_PERIOD", + "text": "៕" + }, + { + "id": "K_SLASH", + "text": "?" + }, + { + "id": "T_new_390", + "text": "", + "width": "10", + "sp": "10" + } + ] + }, + { + "id": 5, + "key": [ + { + "id": "K_LCONTROL", + "text": "*AltGr*", + "width": "160", + "sp": "1", + "nextlayer": "rightalt" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "160", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": "", + "width": "930" + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "160", + "sp": "1" + } + ] + } + ] + } + ], + "font": "Khmer Busra Kbd", + "fontsize": "0.8em" + }, + "phone": { + "layer": [ + { + "id": "default", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_Q", + "text": "ឆ", + "pad": "", + "sk": [ + { + "text": "ឈ", + "id": "K_Q", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1786" + }, + { + "text": "", + "id": "T_17D2_1788" + } + ] + }, + { + "id": "K_W", + "text": "", + "sk": [ + { + "text": "", + "id": "K_W", + "layer": "shift" + } + ] + }, + { + "id": "K_E", + "text": "", + "sk": [ + { + "text": "", + "id": "K_E", + "layer": "shift" + }, + { + "text": "", + "id": "K_S", + "layer": "shift" + }, + { + "text": "", + "id": "K_V", + "layer": "shift" + }, + { + "text": "ឯ", + "id": "U_17AF" + }, + { + "text": "ឰ", + "id": "U_17B0" + } + ] + }, + { + "id": "K_R", + "text": "រ", + "sk": [ + { + "text": "", + "id": "T_17D2_179A" + }, + { + "text": "ឫ", + "id": "U_17AB" + }, + { + "text": "ឬ", + "id": "U_17AC" + } + ] + }, + { + "id": "K_T", + "text": "ត", + "sk": [ + { + "text": "ទ", + "id": "K_T", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_178F" + }, + { + "text": "", + "id": "T_17D2_1791", + "layer": "default" + } + ] + }, + { + "id": "K_Y", + "text": "យ", + "sk": [ + { + "text": "", + "id": "T_17D2_1799" + } + ] + }, + { + "id": "K_U", + "text": "", + "sk": [ + { + "text": "", + "id": "K_U", + "layer": "shift" + }, + { + "text": "", + "id": "K_Y", + "layer": "shift" + }, + { + "text": "ឧ", + "id": "U_17A7" + }, + { + "text": "ឪ", + "id": "U_17AA", + "layer": "shift" + }, + { + "text": "ឩ", + "id": "U_17A9", + "layer": "shift" + }, + { + "text": "ឨ", + "id": "U_17A8" + } + ] + }, + { + "id": "K_I", + "text": "", + "sk": [ + { + "text": "", + "id": "K_I", + "layer": "shift" + }, + { + "text": "ឥ", + "id": "U_17A5" + }, + { + "text": "ឦ", + "id": "U_17A6", + "layer": "shift" + } + ] + }, + { + "id": "K_O", + "text": "", + "sk": [ + { + "text": "", + "id": "K_O", + "layer": "shift" + }, + { + "text": "", + "id": "K_LBRKT" + }, + { + "text": "", + "id": "K_LBRKT", + "layer": "shift" + }, + { + "text": "", + "id": "K_COLON", + "layer": "shift" + }, + { + "text": "ឱ", + "id": "U_17B1" + }, + { + "text": "ឲ", + "id": "U_17B2" + }, + { + "text": "ឳ", + "id": "U_17B3", + "layer": "shift" + } + ] + }, + { + "id": "K_P", + "text": "ផ", + "sk": [ + { + "text": "ភ", + "id": "K_P", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1795" + }, + { + "text": "", + "id": "T_17D2_1797", + "layer": "default" + } + ] + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "K_A", + "text": "", + "pad": "", + "width": "100", + "sk": [ + { + "text": "", + "id": "K_A", + "layer": "shift" + } + ] + }, + { + "id": "K_S", + "text": "ស", + "sk": [ + { + "text": "", + "id": "T_17D2_179F" + }, + { + "text": "ឝ", + "id": "U_179D" + }, + { + "text": "ឞ", + "id": "U_179E" + } + ] + }, + { + "id": "K_D", + "text": "ដ", + "sk": [ + { + "text": "ឌ", + "id": "K_D", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_178A" + }, + { + "text": "", + "id": "T_17D2_178C", + "layer": "default" + } + ] + }, + { + "id": "K_F", + "text": "ថ", + "sk": [ + { + "text": "ធ", + "id": "K_F", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1790" + }, + { + "text": "", + "id": "T_17D2_1792", + "layer": "default" + } + ] + }, + { + "id": "K_G", + "text": "ង", + "sk": [ + { + "text": "អ", + "id": "K_G", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1784" + }, + { + "text": "", + "id": "T_17D2_17A2", + "layer": "default" + } + ] + }, + { + "id": "K_H", + "text": "ហ", + "sk": [ + { + "text": "", + "id": "T_17D2_17A0" + }, + { + "text": "ះ", + "id": "K_H", + "layer": "shift" + }, + { + "text": "ៈ", + "id": "U_17C8" + } + ] + }, + { + "id": "K_J", + "text": "ញ", + "layer": "shift", + "sk": [ + { + "text": "", + "id": "T_17D2_1789" + } + ] + }, + { + "id": "K_K", + "text": "ក", + "sk": [ + { + "text": "គ", + "id": "K_K", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1780" + }, + { + "text": "", + "id": "T_17D2_1782" + } + ] + }, + { + "id": "K_L", + "text": "ល", + "sk": [ + { + "text": "ឡ", + "id": "K_L", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_179B" + }, + { + "text": "ឭ", + "id": "U_17AD" + }, + { + "text": "ឮ", + "id": "U_17AE" + } + ] + }, + { + "id": "K_COLON", + "text": "" + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "K_Z", + "text": "ឋ", + "pad": "", + "width": "", + "sk": [ + { + "text": "ឍ", + "id": "K_Z", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_178B" + }, + { + "text": "", + "id": "T_17D2_178D", + "layer": "default" + } + ] + }, + { + "id": "K_X", + "text": "ខ", + "sk": [ + { + "text": "ឃ", + "id": "K_X", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1781" + }, + { + "text": "", + "id": "T_17D2_1783", + "layer": "default" + } + ] + }, + { + "id": "K_C", + "text": "ច", + "sk": [ + { + "text": "ជ", + "id": "K_C", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1785" + }, + { + "text": "", + "id": "T_17D2_1787", + "layer": "default" + } + ] + }, + { + "id": "K_V", + "text": "វ", + "sk": [ + { + "text": "", + "id": "T_17D2_179C" + } + ] + }, + { + "id": "K_B", + "text": "ប", + "sk": [ + { + "text": "ព", + "id": "K_B", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1794" + }, + { + "text": "", + "id": "T_17D2_1796", + "layer": "default" + } + ] + }, + { + "id": "K_N", + "text": "ន", + "sk": [ + { + "text": "ណ", + "id": "K_N", + "layer": "shift" + }, + { + "text": "", + "id": "T_17D2_1793" + }, + { + "text": "", + "id": "T_17D2_178E", + "layer": "default" + } + ] + }, + { + "id": "K_M", + "text": "ម", + "sk": [ + { + "text": "", + "id": "T_17D2_1798" + }, + { + "text": "", + "id": "K_M", + "layer": "shift" + } + ] + }, + { + "id": "K_COMMA", + "text": "", + "sk": [ + { + "text": "", + "id": "K_COMMA", + "layer": "shift" + }, + { + "text": "", + "id": "K_6", + "layer": "shift" + }, + { + "text": "", + "id": "K_7", + "layer": "shift" + }, + { + "text": "", + "id": "K_8", + "layer": "shift" + }, + { + "text": "", + "id": "K_HYPHEN", + "layer": "shift" + }, + { + "text": "", + "id": "U_17D1", + "layer": "shift" + }, + { + "text": "", + "id": "U_17DD", + "layer": "shift" + }, + { + "text": "", + "id": "U_17CE", + "layer": "shift" + } + ] + }, + { + "id": "K_QUOTE", + "text": "", + "width": "100", + "sk": [ + { + "text": "", + "id": "K_QUOTE", + "layer": "shift" + }, + { + "text": "", + "id": "K_SLASH" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "100", + "sp": "1" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_NUMLOCK", + "text": "១២៣", + "width": "140", + "sp": "1", + "nextlayer": "numeric" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "120", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": "​", + "width": "555", + "sp": "0", + "sk": [ + { + "text": " ", + "id": "U_0020", + "layer": "default" + } + ] + }, + { + "id": "K_PERIOD", + "text": "។", + "width": "120", + "sk": [ + { + "text": "៕", + "id": "K_PERIOD", + "layer": "shift" + }, + { + "text": "!", + "id": "U_0021" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "140", + "sp": "1" + } + ] + } + ] + }, + { + "id": "numeric", + "row": [ + { + "id": 1, + "key": [ + { + "id": "K_1", + "text": "១", + "pad": "", + "sk": [ + { + "text": "1", + "id": "U_0031" + } + ] + }, + { + "id": "K_2", + "text": "២", + "sk": [ + { + "text": "2", + "id": "U_0032" + } + ] + }, + { + "id": "K_3", + "text": "៣", + "sk": [ + { + "text": "3", + "id": "U_0033" + } + ] + }, + { + "id": "K_4", + "text": "៤", + "sk": [ + { + "text": "4", + "id": "U_0034" + } + ] + }, + { + "id": "K_5", + "text": "៥", + "sk": [ + { + "text": "5", + "id": "U_0035" + } + ] + }, + { + "id": "K_6", + "text": "៦", + "sk": [ + { + "text": "6", + "id": "U_0036" + } + ] + }, + { + "id": "K_7", + "text": "៧", + "sk": [ + { + "text": "7", + "id": "U_0037" + } + ] + }, + { + "id": "K_8", + "text": "៨", + "sk": [ + { + "text": "8", + "id": "U_0038" + } + ] + }, + { + "id": "K_9", + "text": "៩", + "sk": [ + { + "text": "9", + "id": "U_0039" + } + ] + }, + { + "id": "K_0", + "text": "០", + "sk": [ + { + "text": "0", + "id": "U_0030" + }, + { + "text": "", + "id": "U_17D3" + } + ] + } + ] + }, + { + "id": 2, + "key": [ + { + "id": "U_0040", + "text": "@", + "pad": "", + "sk": [ + { + "text": "©", + "id": "U_00A9" + }, + { + "text": "®", + "id": "U_00AE" + } + ] + }, + { + "id": "U_0023", + "text": "#", + "sk": [ + { + "text": "№", + "id": "U_2116" + }, + { + "text": "~", + "id": "U_007E" + } + ] + }, + { + "id": "U_17DB", + "text": "៛", + "sk": [ + { + "text": "$", + "id": "U_0024" + }, + { + "text": "฿", + "id": "U_0E3F" + }, + { + "text": "¢", + "id": "U_00A2" + }, + { + "text": "£", + "id": "U_00A3" + }, + { + "text": "¥", + "id": "U_00A5" + } + ] + }, + { + "id": "U_0026", + "text": "&" + }, + { + "id": "U_0025", + "text": "%", + "sk": [ + { + "text": "‰", + "id": "U_2030" + }, + { + "text": "‱", + "id": "U_2031" + } + ] + }, + { + "id": "U_002B", + "text": "+", + "sk": [ + { + "text": "-", + "id": "U_002D" + }, + { + "text": "×", + "id": "U_00D7" + }, + { + "text": "÷", + "id": "U_00F7" + }, + { + "text": "±", + "id": "U_00B1" + } + ] + }, + { + "id": "U_003D", + "text": "=", + "sk": [ + { + "text": "_", + "id": "U_005F" + }, + { + "text": "≠", + "id": "U_2260" + } + ] + }, + { + "id": "U_002A", + "text": "*", + "sk": [ + { + "text": "^", + "id": "U_005E" + } + ] + }, + { + "id": "U_003F", + "text": "?", + "sk": [ + { + "text": "¿", + "id": "U_00BF" + } + ] + }, + { + "id": "U_0021", + "text": "!", + "sk": [ + { + "text": "¡", + "id": "U_00A1" + } + ] + } + ] + }, + { + "id": 3, + "key": [ + { + "id": "U_2018", + "text": "‘", + "sk": [ + { + "text": "’", + "id": "U_2019" + } + ] + }, + { + "id": "U_201C", + "text": "“", + "sk": [ + { + "text": "”", + "id": "U_201D" + } + ] + }, + { + "id": "U_00AB", + "text": "«", + "pad": "", + "sk": [ + { + "text": "»", + "id": "U_00BB" + } + ] + }, + { + "id": "U_002F", + "text": "/", + "sk": [ + { + "text": "\\", + "id": "U_005C" + }, + { + "text": "|", + "id": "U_007C" + }, + { + "text": "¦", + "id": "U_00A6" + } + ] + }, + { + "id": "U_0028", + "text": "(", + "sk": [ + { + "text": ")", + "id": "U_0029" + }, + { + "text": "[", + "id": "U_005B" + }, + { + "text": "]", + "id": "U_005D" + }, + { + "text": "{", + "id": "U_007B" + }, + { + "text": "}", + "id": "U_007D" + } + ] + }, + { + "id": "U_17D9", + "text": "៙", + "sk": [ + { + "text": "៚", + "id": "U_17DA" + }, + { + "text": "ៜ", + "id": "U_17DC" + }, + { + "text": "§", + "id": "U_00A7" + }, + { + "text": "Ø", + "id": "U_00D8" + } + ] + }, + { + "id": "U_17D7", + "text": "ៗ" + }, + { + "id": "U_003C", + "text": "<", + "sk": [ + { + "text": "≤", + "id": "U_2264" + }, + { + "text": ">", + "id": "U_003E" + }, + { + "text": "≥", + "id": "U_2265" + } + ] + }, + { + "id": "U_17D6", + "text": "៖", + "sk": [ + { + "text": ":", + "id": "U_003A" + }, + { + "text": ";", + "id": "U_003B" + }, + { + "text": "…", + "id": "U_2026" + } + ] + }, + { + "id": "K_BKSP", + "text": "*BkSp*", + "width": "", + "sp": "1" + } + ] + }, + { + "id": 4, + "key": [ + { + "id": "K_LCONTROL", + "text": "១២៣", + "width": "140", + "sp": "2", + "nextlayer": "default" + }, + { + "id": "K_LOPT", + "text": "*Menu*", + "width": "120", + "sp": "1" + }, + { + "id": "K_SPACE", + "text": "​", + "width": "555", + "sp": "0", + "layer": "shift", + "sk": [] + }, + { + "id": "K_PERIOD", + "text": "។", + "width": "120", + "sk": [ + { + "text": "៕", + "id": "K_PERIOD", + "layer": "shift" + }, + { + "text": "!", + "id": "U_0021" + }, + { + "text": "?", + "id": "U_003F" + } + ] + }, + { + "id": "K_ENTER", + "text": "*Enter*", + "width": "140", + "sp": "1" + } + ] + } + ] + } + ], + "displayUnderlying": false, + "font": "Khmer Busra Kbd", + "fontsize": "0.8em" + } +} \ No newline at end of file diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kmn b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kmn new file mode 100644 index 0000000000..b7919afca3 --- /dev/null +++ b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kmn @@ -0,0 +1,642 @@ +store(&VERSION) '10.0' +store(&NAME) "Khmer Angkor" +store(©RIGHT) '© 2015-2022 SIL International' +store(&MESSAGE) "More than just a Khmer Unicode keyboard." +store(&TARGETS) 'any' +store(&LAYOUTFILE) 'khmer_angkor.keyman-touch-layout' +store(&KEYBOARDVERSION) '1.3' +store(&BITMAP) 'khmer_angkor.ico' +store(&VISUALKEYBOARD) 'khmer_angkor.kvks' + +begin Unicode > use(main) + + + +c ==============================================STORES============================================== + + + +c 33 consonants and two deprecated consonants + +store(c_key) [K_K] [K_X] [SHIFT K_K] [SHIFT K_X] [K_G] \ + [K_C] [K_Q] [SHIFT K_C] [SHIFT K_Q] [SHIFT K_J] \ + [K_D] [K_Z] [SHIFT K_D] [SHIFT K_Z] [SHIFT K_N] \ + [K_T] [K_F] [SHIFT K_T] [SHIFT K_F] [K_N] \ + [K_B] [K_P] [SHIFT K_B] [SHIFT K_P] [K_M] \ + [K_Y] [K_R] [K_L] [K_V] [K_S] [K_H] [SHIFT K_L] [SHIFT K_G] \ + [RALT K_K] [RALT K_B] +store(c_out) U+1780 U+1781 U+1782 U+1783 U+1784 \ + U+1785 U+1786 U+1787 U+1788 U+1789 \ + U+178A U+178B U+178C U+178D U+178E \ + U+178F U+1790 U+1791 U+1792 U+1793 \ + U+1794 U+1795 U+1796 U+1797 U+1798 \ + U+1799 U+179A U+179B U+179C U+179F U+17A0 U+17A1 U+17A2 \ + U+179D U+179E c deprecated, but they are used in minority languages + +c All genuine dependent vowels + +store(v_gen_key) [K_A] [K_I] [SHIFT K_I] [K_W] [SHIFT K_W] [K_U] [SHIFT K_U] [SHIFT K_Y] \ + [K_COLON] [SHIFT K_LBRKT] [K_LBRKT] [K_E] [SHIFT K_E] [SHIFT K_S] [K_O] [SHIFT K_O] +store(v_gen) U+17B6 U+17B7 U+17B8 U+17B9 U+17BA U+17BB U+17BC U+17BD \ + U+17BE U+17BF U+17C0 U+17C1 U+17C2 U+17C3 U+17C4 U+17C5 + +c All pseudo dependent vowels + +store(v_pseudo_key) [SHIFT K_M] [SHIFT K_H] [RALT K_QUOTE] +store(v_pseudo) U+17C6 U+17C7 U+17C8 + +c Both genuine and pseudo vowels + +store(v_key) outs(v_gen_key) outs(v_pseudo_key) +store(v_out) outs(v_gen) outs(v_pseudo) +store(v_any) outs(v_out) + +c These seven vowels can be concatenated with Reahmuk (U+17C7) to make េះ ោះ ុះ ិះ ីះ ឹះ and ែះ. + +store(v_combo_R) U+17C1 U+17C4 U+17BB U+17B7 U+17B8 U+17B9 U+17C2 + +c these two vowels can be concatenated with Nikahit (U+17C6) to make ាំ and ុំ. + +store(v_combo_N) U+17B6 U+17BB +store(v_combo) outs(v_combo_R) outs(v_combo_N) + +c Independent vowels + +store(ind_v_key) [K_HYPHEN] [RALT K_I] [SHIFT K_RBRKT] [RALT K_T] [RALT K_LBRKT] [K_RBRKT] [RALT K_R] [SHIFT K_R] \ + [SHIFT K_BKSLASH] [K_BKSLASH] [RALT K_E] [RALT K_P] [RALT K_O] [K_EQUAL] [RALT K_RBRKT] +store(ind_v_out) U+17A5 U+17A6 U+17A7 U+17A8 U+17A9 U+17AA U+17AB U+17AC \ + U+17AD U+17AE U+17AF U+17B0 U+17B1 U+17B2 U+17B3 + +c Diacritics + +store(diacritic_key) [K_QUOTE] [SHIFT K_7] [SHIFT K_HYPHEN] [SHIFT K_8] [SHIFT K_6] [RALT K_QUOTE] \ + [RALT K_EQUAL] [RALT K_3] [RALT K_W] [RALT K_Q] [K_J] +store(diacritic_out) U+17CB U+17D0 U+17CC U+17CF U+17CD U+17C8 \ + U+17CE U+17D1 U+17DD U+17DC U+17D2 + +c Consonant shifter--Muusikatoan(U+17C9) and Triisap(U+17CA) + +store(c_shifter_key) [SHIFT K_QUOTE] [K_SLASH] +store(c_shifter) U+17C9 U+17CA + +c punctuations + +store(punct_key) [K_PERIOD] [SHIFT K_PERIOD] [RALT K_COLON] [SHIFT K_2] [RALT K_L] [RALT K_6] [RALT K_7] [RALT K_M] +store(punct_out) U+17D4 U+17D5 U+17D6 U+17D7 U+17D8 U+17D9 U+17DA U+17D3 + +store(latin_punct_key) [K_BKQUOTE] [SHIFT K_BKQUOTE] [SHIFT K_9] [SHIFT K_0] [SHIFT K_1] [SHIFT K_3] \ + [SHIFT K_5] [SHIFT K_EQUAL] [SHIFT K_SLASH] [RALT K_9] [RALT K_0] [RALT K_BKSLASH] \ + [RALT K_2] [RALT K_8] [RALT K_COMMA] [RALT K_D] [RALT K_PERIOD] [RALT K_SLASH] \ + [RALT K_Y] [RALT K_U] [RALT K_BKQUOTE] [RALT K_1] [RALT K_A] [RALT K_S] \ + [RALT K_F] [RALT K_G] [RALT K_HYPHEN] [RALT K_H] [RALT K_J] [RALT K_N] \ + [RALT K_Z] [RALT K_X] [RALT K_C] [RALT K_V] +store(latin_punct_out) U+00AB U+00BB U+0028 U+0029 U+0021 U+0022 \ + U+0025 U+003D U+003F U+007B U+007D U+005C \ + U+0040 U+002A U+002C U+00D7 U+002E U+002F \ + U+005B U+005D U+200D U+200C U+002B U+002D \ + U+00F7 U+003A U+2248 U+2018 U+2019 U+003B \ + U+003C U+003E U+0023 U+0026 +c white space, ZWSP, ZWJ +store(spaces_key) [K_SPACE] [SHIFT K_SPACE] [RALT K_SPACE] +store(spaces_out) U+200B U+0020 U+00A0 + +c Currency: Riel, Dollar and Euro + +store(currency_key) [SHIFT K_4] [RALT K_4] [RALT K_5] +store(currency_out) U+17DB U+0024 U+20AC + +c Khmer digits 0 through 9 + +store(digit_key) [K_0] [K_1] [K_2] [K_3] [K_4] [K_5] [K_6] [K_7] [K_8] [K_9] +store(digit_out) U+17E0 U+17E1 U+17E2 U+17E3 U+17E4 U+17E5 U+17E6 U+17E7 U+17E8 U+17E9 + +c Khmer Lek Attak (a.k.a. divination lore) +store(lek_attak_key) [SHIFT RALT K_0] [SHIFT RALT K_1] [SHIFT RALT K_2] [SHIFT RALT K_3] [SHIFT RALT K_4] \ + [SHIFT RALT K_5] [SHIFT RALT K_6] [SHIFT RALT K_7] [SHIFT RALT K_8] [SHIFT RALT K_9] +store(lek_attak_out) U+17F0 U+17F1 U+17F2 U+17F3 U+17F4 \ + U+17F5 U+17F6 U+17F7 U+17F8 U+17F9 + +c Lunar date format (Khmer style) + +store(lunar_date_key) [SHIFT RALT K_A] [SHIFT RALT K_B] [SHIFT RALT K_C] [SHIFT RALT K_D] [SHIFT RALT K_E] \ + [SHIFT RALT K_F] [SHIFT RALT K_G] [SHIFT RALT K_H] [SHIFT RALT K_I] [SHIFT RALT K_J] \ + [SHIFT RALT K_K] [SHIFT RALT K_L] [SHIFT RALT K_M] [SHIFT RALT K_N] [SHIFT RALT K_O] \ + [SHIFT RALT K_P] [SHIFT RALT K_Q] [SHIFT RALT K_R] [SHIFT RALT K_S] [SHIFT RALT K_T] \ + [SHIFT RALT K_U] [SHIFT RALT K_V] [SHIFT RALT K_W] [SHIFT RALT K_X] [SHIFT RALT K_Y] \ + [SHIFT RALT K_Z] [SHIFT RALT K_COLON] [SHIFT RALT K_COMMA] [SHIFT RALT K_PERIOD] [SHIFT RALT K_LBRKT] \ + [SHIFT RALT K_RBRKT] [SHIFT RALT K_QUOTE] +store(lunar_date_out) U+19EC U+19FB U+19F9 U+19EE U+19E2 \ + U+19EF U+19F0 U+19F1 U+19E7 U+19F2 \ + U+19F3 U+19F4 U+19FD U+19FC U+19E8 \ + U+19E9 U+19E0 U+19E3 U+19ED U+19E4 \ + U+19E6 U+19FA U+19E1 U+19F8 U+19E5 \ + U+19F7 U+19F5 U+19FE U+19FF U+19EA \ + U+19EB U+19F6 + +c Subscripts​ for mobile/table layouts + +store(input_subcons) \ + [T_17D2_1780] [T_17D2_1781] [T_17D2_1782] [T_17D2_1783] [T_17D2_1784] [T_17D2_1785] [T_17D2_1786] [T_17D2_1787] \ + [T_17D2_1788] [T_17D2_1789] [T_17D2_178A] [T_17D2_178B] [T_17D2_178C] [T_17D2_178D] [T_17D2_178E] [T_17D2_178F] \ + [T_17D2_1790] [T_17D2_1791] [T_17D2_1792] [T_17D2_1793] [T_17D2_1794] [T_17D2_1795] [T_17D2_1796] [T_17D2_1797] \ + [T_17D2_1798] [T_17D2_1799] [T_17D2_179A] [T_17D2_179B] [T_17D2_179C] [T_17D2_179D] [T_17D2_179E] [T_17D2_179F] \ + [T_17D2_17A0] [T_17D2_17A1] [T_17D2_17A2] + +store(subcons) \ + U+1780 U+1781 U+1782 U+1783 U+1784 U+1785 U+1786 U+1787 \ + U+1788 U+1789 U+178A U+178B U+178C U+178D U+178E U+178F \ + U+1790 U+1791 U+1792 U+1793 U+1794 U+1795 U+1796 U+1797 \ + U+1798 U+1799 U+179A U+179B U+179C U+179D U+179E U+179F \ + U+17A0 U+17A1 U+17A2 + +c Arabic digits 0 through 9 + +store(arabic_digit_key) [U_0030] [U_0031] [U_0032] [U_0033] [U_0034] [U_0035] [U_0036] [U_0037] [U_0038] [U_0039] +store(arabic_digit_out) U+0030 U+0031 U+0032 U+0033 U+0034 U+0035 U+0036 U+0037 U+0038 U+0039 + +c These stores are for consonant (cluster) and consonant shifter configuration + +store(v_above) U+17B7 U+17B8 U+17B9 U+17BA \ + U+17BE U+17D0 c These vowels are rendered above the base consonant. +store(shiftable_c_1st) U+179F U+17A0 U+17A2 c These consonants shift to the 2nd series when adding U+17CA to them. +store(shiftable_BA) U+1794 c BA is unique because it can be used with both U+17CA (shift to 2nd) and and U+179C (shift to PA, still in 1st series). +store(shiftable_c_2nd) U+1784 U+1789 U+1798 U+1799 \ + U+179A U+179C U+1793 U+179B c These consonants shift to the 1st series when adding U+17C9 to them. +store(shiftable_c_2nd_with_BA) outs(shiftable_c_2nd) outs(shiftable_BA) +store(c_2nd_combo_LO) U+1799 U+1798 U+1784 U+1794 \ + U+179C c These can be combined with U+179B to make a 2nd series consonant cluster. +store(c_2nd_combo_MO) U+1799 U+179B U+1784 U+179A c These can be combined with U+1798 to make a 2nd series consonant cluster. +store(c_1st_combo_LO) U+1794 U+17A0 U+17A2 c they can be combined with U+179B to make a 1st series consonant cluster. +store(c_1st_combo_MO) U+17A0 U+179F U+17A2 c they can be combined with U+1798 to make a 1st series consonant cluster. +store(c_combo_SA) U+1794 U+1799 U+179B U+1798 \ + U+1793 U+1789 U+1784 U+179A \ + U+179C U+17A2 c they can be combined with U+179F to make a 1st series consonant cluster. +store(c_combo_QA) U+1786 U+1788 U+1794 U+1795 \ + U+178F U+1791 c they can be combined with U+17A2 to make a 1st series consonant cluster. +store(c_combo_HA) U+179C U+17A3 c they can be combined with U+17A0 to make a 1st series consonant cluster. + + + +c ==============================================BASIC RULES & CONSTRAINTS/ROTATIONS============================================== + + + +group(main) using keys + +c Basic rules with RALT key + + + any(c_key) > index(c_out,1) + + any(v_key) > index(v_out,1) + + any(ind_v_key) > index(ind_v_out,1) + + any(diacritic_key) > index(diacritic_out,1) + + any(c_shifter_key) > index(c_shifter,1) + + any(punct_key) > index(punct_out,1) + + any(latin_punct_key) > index(latin_punct_out,1) + + any(currency_key) > index(currency_out,1) + + any(digit_key) > index(digit_out,1) + + any(lek_attak_key) > index(lek_attak_out,1) + + any(lunar_date_key) > index(lunar_date_out,1) + + any(spaces_key) > index(spaces_out,1) + +c two-unicode-code-point vowels + ++ [SHIFT K_A] > U+17B6 U+17C6 ++ [SHIFT K_V] > U+17C1 U+17C7 ++ [SHIFT K_COLON] > U+17C4 U+17C7 ++ [K_COMMA] > U+17BB U+17C6 ++ [SHIFT K_COMMA] > U+17BB U+17C7 + +c Constraints + +any(v_gen) + [K_QUOTE] > context beep c no Bantoc after any genuine vowel +any(v_pseudo) + [K_QUOTE] > context beep c no Bantoc after any pseudo vowel +any(c_shifter) + [K_QUOTE] > context beep c no Bantoc after Triisap/Muusikatoan +U+17D2 any(c_out) + [K_QUOTE] > context beep c no Bantoc on a subscript +any(c_shifter) + any(c_shifter_key) > context beep c no two Triisap/Muusikatoan + +c Rotation + +U+17C7 + [SHIFT K_H] > U+17C8 c U+17C7 is changed to U+17C8 when pressing [SHIFT K_H]. +U+17C8 + [SHIFT K_H] > U+17C7 c U+17C8 is changed to U+17C7 when K_H is pressed. +c any(v_gen) U+17C7 + [SHIFT K_H] > context beep c Don't rotate between U+17C7 and U+17C8. + +c Press Space twice to get a White Space + +U+200B + [K_SPACE] > U+0020 + +c One backspace deletes a two-part vowels (i.e. psuedoVowel + U+17C7) + +any(v_combo_N) U+17C6 + [K_BKSP] > nul +any(v_combo_R) U+17C7 + [K_BKSP] > nul + +c When pressing [K_U] after ាំ and ុំ, the U+17BB is converted to a respective consonant shifter placing before them (ាំ and ុំ). + +any(shiftable_c_1st) U+17B6 U+17C6 + [K_U] > context(1) U+17CA context(2) context(3) c fix ស ាំ ុ > ស៊ាំ +any(shiftable_c_2nd_with_BA) U+17B6 U+17C6 + [K_U] > context(1) U+17C9 context(2) context(3) c fix ម ាំ ុ > ម៉ាំ + +c Consonant shifter constraints (beep when the consonant shifter is used in inappropriate environment) + +any(shiftable_c_1st) + [SHIFT K_QUOTE] > context U+17C9 beep +any(shiftable_c_2nd_with_BA) + [K_SLASH] > context U+17CA beep + +c 1st series consonant clusters + +any(c_combo_QA) U+17D2 U+17A2 + [SHIFT K_QUOTE] > context U+17C9 beep +U+179B U+17D2 any(c_1st_combo_LO) + [SHIFT K_QUOTE] > context U+17C9 beep +U+1798 U+17D2 any(c_1st_combo_MO) + [SHIFT K_QUOTE] > context U+17C9 beep +U+179F U+17D2 any(c_combo_SA) + [SHIFT K_QUOTE] > context U+17C9 beep +any(c_combo_HA) U+17D2 U+17A0 + [SHIFT K_QUOTE] > context U+17C9 beep +U+17A2 U+17D2 U+1784 + [SHIFT K_QUOTE] > context U+17C9 beep +U+17A2 U+17D2 U+179C + [SHIFT K_QUOTE] > context U+17C9 beep + +c 2nd series consonant clusters + +U+179B U+17D2 any(c_2nd_combo_LO) + [K_SLASH] > context U+17CA beep +U+1798 U+17D2 any(c_2nd_combo_MO) + [K_SLASH] > context U+17CA beep + + +c ==============================================MOBILE/TABLET TOUCH LAYOUT============================================== + + + ++ any(input_subcons) > U+17D2 index(subcons, 1) + +c delete a subscript (a subscript sign + a consonant) upon a backspace + +platform('touch') U+17D2 any(c_out) + [K_BKSP] > nul c working OK + + + [K_NPSTAR] > U+002A + + [SHIFT K_NPSTAR] > U+002A + + [K_NPPLUS] > U+002B + + [SHIFT K_NPPLUS] > U+002B + + [K_NPMINUS] > U+002D + + [SHIFT K_NPMINUS] > U+002D + + [K_NPDOT] > U+002E + + [SHIFT K_NPDOT] > U+002E + + [K_NPSLASH] > U+002F + + [SHIFT K_NPSLASH] > U+002F + + + +c ==============================================NORMALIZATION============================================== + + + +match > use(normalise) + +group(normalise) + +c Illegitimate vowel combinations should be transformed to the legitimate ones (Case #6 and #7). + +U+17C1 U+17B6 > U+17C4 c when type េ and ា, tranform them to ោ +U+17B6 U+17C1 > U+17C4 c when type ា and េ, tranform them to ោ +U+17C1 U+17B8 > U+17BE c when type េ and ី , tranform them to ើ +U+17B8 U+17C1 > U+17BE c when type ី and េ, tranform them to ើ + +c Illegitimate vowel combinations should be transformed to the legitimate ones (Case #5). + +U+17C6 U+17BB > U+17BB U+17C6 c when type ំ and ុ , tranform them to ុំ +U+17C6 U+17B6 > U+17B6 U+17C6 c when type ំ and ា, tranform them to ាំ + + +c Rotate vowels + +any(v_gen) any(v_gen) > context(2) c the last vowel stroke replaces the previous one. + +c Rotation of two-part vowels + +any(v_gen) any(v_pseudo) any(v_gen) > context(3) c a two-part vowel rotates to a genuine vowel. +any(v_gen) any(v_pseudo) any(v_pseudo) > context(3) c a two-part vowel rotates to a pseudo vowel. +any(v_gen) any(v_gen) any(v_pseudo) > context(2) context(3) c a genuine vowel rotates to a two-part vowel. +any(v_pseudo) any(v_gen) any(v_pseudo) > context(2) context(3) c a pseudo vowel roates to a two-part vowel. +any(v_gen) any(v_pseudo) any(v_gen) any(v_pseudo) > context(3) context(4) c a two-part vowel rotates to another two-part vowel. +any(v_pseudo) any(v_pseudo) > context(2) c a pseudo vowel rotates to another pseudo vowel. +c any(v_pseudo) any(v_gen) > context(2) c a pseudo vowel roates to a genuine vowel. + +c Delete extraneous coeng markers + +U+17D2 U+17D2 > context(1) c no two coengs are allowed. +U+17D2 any(v_any) > context(2) c The coeng is deleted when a vowel is put after it. +U+17D2 any(v_gen) any(v_pseudo) > context(2) context(3) c The coeng is deleted when a pseudo vowel is put after it. + +c Case #1: when a subscript is typed after a vowel, the subscript should be automatically moved to before the vowel. + +any(v_any) U+17D2 any(subcons) > context(2) context(3) context(1) c a vowel has to come after a subscript. +any(v_combo_N) U+17C6 U+17D2 any(subcons) > context(3) context(4) context(1) context(2) c these two-part vowels have to come after a subscript. +any(v_combo_R) U+17C7 U+17D2 any(subcons) > context(3) context(4) context(1) context(2) c these two-part vowels have to come after a subscript. + +c a subscript placed after a shifter and a vowel (a genuine/pseudo vowel or a two-part vowel) has to move to before them. + +any(c_shifter) any(v_any) U+17D2 any(subcons) > context(3) context(4) context(1) context(2) c after a genuine/pseudo vowel +any(c_shifter) any(v_combo_N) U+17C6 U+17D2 any(subcons) > context(4) context(5) context(1) context(2) context(3) c after a two-part vowel +any(c_shifter) any(v_combo_R) U+17C7 U+17D2 any(subcons) > context(4) context(5) context(1) context(2) context(3) c after a two-part vowel + +c Case #2: when [D2+9A] is typed before a subscript, it should be moved to after it. + +U+17D2 U+178A U+17D2 U+179A > context(1) U+178F context(3) context(4) c change subscript ្ដ to ្ត after ្រ +U+17D2 U+179A U+17D2 U+178A > context(3) U+178F context(1) context(2) c ្ដ placed after ្រ has to be changed to ្ត and placed before ្រ + +U+17D2 U+178A any(v_any) U+17D2 U+179A > context(1) U+178F context(4) context(5) context(3) c fixed 6e +U+17D2 U+178A any(v_combo_N) U+17C6 U+17D2 U+179A > context(1) U+178F context(5) context(6) context(3) context(4) +U+17D2 U+178A any(v_combo_R) U+17C7 U+17D2 U+179A > context(1) U+178F context(5) context(6) context(3) context(4) + +U+17D2 U+179A any(v_any) U+17D2 U+178A > context(1) U+178F context(4) context(2) context(3) c fixed 6g +U+17D2 U+179A any(v_combo_N) U+17C6 U+17D2 U+178A > context(1) U+178F context(5) context(2) context(3) context(4) +U+17D2 U+179A any(v_combo_R) U+17C7 U+17D2 U+178A > context(1) U+178F context(5) context(2) context(3) context(4) + +U+17D2 U+179A any(c_shifter) U+17D2 any(subcons) > context(4) context(5) context(1) context(2) context(3) c when a shifter intervenes, move it to the end. +U+17D2 U+179A U+17D2 any(subcons) > context(3) context(4) context(1) context(2) c move any subscript placed after [D2+DA] to before them +U+17D2 U+179A any(v_any) U+17D2 any(subcons) > context(4) context(5) context(1) context(2) context(3) c when a vowel intervenes, move it to the end +U+17D2 U+179A any(v_combo_N) U+17C6 U+17D2 any(subcons) > context(5) context(6) context(1) context(2) context(3) context(4) c when a two-part vowel intervenes, move it to the end too. +U+17D2 U+179A any(v_combo_R) U+17C7 U+17D2 any(subcons) > context(5) context(6) context(1) context(2) context(3) context(4) c (same as stated right above) + +c when a subscript is placed after a consonant shifter, they should be reversed. (Case #3) + +any(c_shifter) U+17D2 any(subcons) > context(2) context(3) context(1) + +c Reordering - Triisap and Muusikatoan store before a vowel and a vowelcomboR and pseudo vowel. + +any(v_any) any(c_shifter) > context(2) context(1) c place either a enguine or pseudo vowel after a consonant shifter +any(v_gen) any(v_pseudo) any(c_shifter) > context(3) context(1) context(2) c place a two-part vowel after a consonant shifter(i.e. មោះ៉ ) +any(c_shifter) any(v_any) any(c_shifter) > context(3) context(2) c when either a genuine or pseudo vowel is in between two consonant shifters, replace the one on the left with the one on the right. +any(c_shifter) any(v_gen) any(v_pseudo) any(c_shifter) > context(2) context(3) context(4) c when a two-part vowel is in between two consonants shifter, replace the one on the left with the one the right. + +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +c + when [BB] is place either before or after an above vowel (ិ ី ឹ ឺ ើ and ាំ) and a Samyok Sannya (Case #4) + +c + the [BB] should transform to a respective consonant shifter placed before the vowel. + +c + the consonant shifter is a Trisap if the base consonant is ស ហ អ + +c + the consonant shifter is a Muusikatoan if the base consonant is ង ញ ម យ រ វ ប and ន ល + +c +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +c consonant clusters --1st > 2nd series (with U+17BB) + +any(c_combo_QA) U+17D2 U+17A2 U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +any(c_combo_QA) U+17D2 U+17A2 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +any(c_combo_QA) U+17D2 U+17A2 any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +any(c_combo_QA) U+17D2 U+17A2 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+179B U+17D2 any(c_1st_combo_LO) U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+179B U+17D2 any(c_1st_combo_LO) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+179B U+17D2 any(c_1st_combo_LO) any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+179B U+17D2 any(c_1st_combo_LO) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+1798 U+17D2 any(c_1st_combo_MO) any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+179F U+17D2 U+1794 U+17BB any(v_above) > context(1) context(2) context(3) U+17C9 context(5) c prevent ស្បុិ from transforming to ស្ប៊ិ​​​, but produce ស្ប៉ិ instead because ប never have Triisap shifted down. +U+179F U+17D2 U+1794 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(5) context(6) +U+179F U+17D2 U+1794 any(v_above) U+17BB > context(1) context(2) context(3) U+17C9 context(4) +U+179F U+17D2 U+1794 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(6) context(7) + +U+179F U+17D2 any(c_combo_SA) U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+179F U+17D2 any(c_combo_SA) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+179F U+17D2 any(c_combo_SA) any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+179F U+17D2 any(c_combo_SA) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +any(c_combo_HA) U+17D2 U+17A0 U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +any(c_combo_HA) U+17D2 U+17A0 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +any(c_combo_HA) U+17D2 U+17A0 any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +any(c_combo_HA) U+17D2 U+17A0 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+17A2 U+17D2 U+1784 U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+17A2 U+17D2 U+1784 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+17A2 U+17D2 U+1784 any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+17A2 U+17D2 U+1784 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+17A2 U+17D2 U+179C U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+17A2 U+17D2 U+179C U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+17A2 U+17D2 U+179C any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) +U+17A2 U+17D2 U+179C U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) + +U+17A0 U+17D2 U+1794 U+17BB any(v_above) > context(1) context(2) context(3) U+17C9 context(5) c change U+17BB preceded by HA and coeng BA to U+17C9 before the above vowel +U+17A0 U+17D2 U+1794 U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(3) context(6) c change U+17BB preceded by HA and coeng BA to U+17C9 before ាំ +U+17A0 U+17D2 U+1794 any(v_above) U+17BB > context(1) context(2) context(3) U+17C9 context(4) c change U+17BB preceded by HA and coeng BA to U+17C9 before the above vowel +U+17A0 U+17D2 U+1794 U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(6) context(7) c change U+17BB preceded by HA and coeng BA to U+17C9 before U+17B6 U+17C6 + + +U+17A0 U+17D2 any(shiftable_c_2nd_with_BA) U+17BB any(v_above) > context(1) context(2) context(3) U+17CA context(5) c change U+17BB preceded by HA and coeng shiftable_c_2nd to U+17CA before the above vowel +U+17A0 U+17D2 any(shiftable_c_2nd_with_BA) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(3) context(6) c change U+17BB preceded by HA and coeng shiftable_c_2nd to U+17CA before ាំ +U+17A0 U+17D2 any(shiftable_c_2nd_with_BA) any(v_above) U+17BB > context(1) context(2) context(3) U+17CA context(4) c change U+17BB preceded by HA and coeng shiftable_c_2nd to U+17CA before the above vowel +U+17A0 U+17D2 any(shiftable_c_2nd_with_BA) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(6) context(7) c change U+17BB preceded by HA and coeng shiftable_c_2nd to U+17CA before U+17B6 U+17C6 + +c consonant clusters --2nd > 1st series (with U+17BB) + +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB any(v_above) > context(1) context(2) context(3) U+17C9 context(5) +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(5) context(6) +U+179B U+17D2 any(c_2nd_combo_LO) any(v_above) U+17BB > context(1) context(2) context(3) U+17C9 context(4) +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(6) context(7) + +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB any(v_above) > context(1) context(2) context(3) U+17C9 context(5) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(5) context(6) +U+1798 U+17D2 any(c_2nd_combo_MO) any(v_above) U+17BB > context(1) context(2) context(3) U+17C9 context(4) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB U+17C6 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(6) context(7) + +c single consonants --1st > 2nd series (with U+17BB) + +any(shiftable_c_1st) U+17BB any(v_above) > context(1) U+17CA context(3) c change U+17BB to U+17CA before the above vowel +any(shiftable_c_1st) U+17BB U+17B6 U+17C6 > context(1) U+17CA context(3) context(4) c change U+17BB to U+17CA before ាំ +any(shiftable_c_1st) any(v_above) U+17BB > context(1) U+17CA context(2) c change U+17BB to U+17CA and place it before the above vowel +any(shiftable_c_1st) U+17BB U+17C6 U+17B6 U+17C6 > context(1) U+17CA context(4) context(5) c change U+17BB U+17C6 to U+17CA + +c single consonants --2nd > 1st series (with U+17BB) + +any(shiftable_c_2nd_with_BA) U+17BB any(v_above) > context(1) U+17C9 context(3) c change U+17BB to U+17C9 before the above vowel +any(shiftable_c_2nd_with_BA) U+17BB U+17B6 U+17C6 > context(1) U+17C9 context(3) context(4) c change U+17BB to U+17C9 before ាំ +any(shiftable_c_2nd_with_BA) any(v_above) U+17BB > context(1) U+17C9 context(2) c change U+17BB to U+17C9 before the above vowel +any(shiftable_c_2nd_with_BA) U+17BB U+17C6 U+17B6 U+17C6 > context(1) U+17C9 context(4) context(5) c change U+17BB U+17C6 to U+17C9 + +c prevent incorrect use of consonant shifter with 2nd series consonant clusters (without U+17BB) + +U+179B U+17D2 any(c_2nd_combo_LO) U+17CA any(v_above) > context(1) context(2) context(3) U+17C9 context(5) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17CA any(v_above) > context(1) context(2) context(3) U+17C9 context(5) +U+179B U+17D2 any(c_2nd_combo_LO) U+17CA any(v_gen) any(v_pseudo) > context(1) context(2) context(3) U+17C9 context(5) context(6) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17CA any(v_gen) any(v_pseudo) > context(1) context(2) context(3) U+17C9 context(5) context(6) + +c single consonants --2nd > 1st series (without U+17BB) + +any(shiftable_c_2nd) U+17CA any(v_above) > context(1) U+17C9 context(3) c change U+17CA to U+17C9 before the above vowel +any(shiftable_c_2nd) U+17CA any(v_gen) any(v_pseudo) > context(1) U+17C9 context(3) context(4) c change U+17CA to U+17C9 before ាំ + +U+17D2 any(shiftable_c_2nd) U+17CA any(v_above) > context c stop ស្រ៊ី from becoming ស្រ៉ី +U+17D2 any(shiftable_c_2nd) U+17CA any(v_gen) any(v_pseudo) > context + +c SPECIAL CASE -- the following clusters may accept either of the two consonant shifters. + +U+1794 U+17D2 U+1799 any(c_shifter) > context +U+179F U+17D2 U+1794 any(c_shifter) > context +U+1786 U+17D2 U+1794 any(c_shifter) > context +U+1794 U+17D2 U+1799 any(c_shifter) > context +U+179F U+17D2 U+1794 any(c_shifter) > context +U+1786 U+17D2 U+1794 any(c_shifter) > context + +c single --1st > 2nd series (without U+17BB) + +any(shiftable_c_1st) U+17C9 any(v_above) > context(1) U+17CA context(3) c change U+17C9 to U+17CA before the above vowel +any(shiftable_c_1st) U+17C9 any(v_gen) any(v_pseudo) > context(1) U+17CA context(3) context(4) c change U+17C9 to U+17CA before ាំ + +c consonant clusters --1st > 2nd series (without U+17BB) + +any(c_combo_QA) U+17D2 U+17A2 U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+179B U+17D2 any(c_1st_combo_LO) U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+1798 U+17D2 any(c_1st_combo_MO) U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+179F U+17D2 U+1794 U+17C9 any(v_above) > context(1) context(2) context(3) U+17C9 context(5) c prevent ស្ប៉ី from transforming to ស្ប៊ី +U+179F U+17D2 any(c_combo_SA) U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +any(c_combo_HA) U+17D2 U+17A0 U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+17A2 U+17D2 U+1784 U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +U+17A2 U+17D2 U+179C U+17C9 any(v_above) > context(1) context(2) context(3) U+17CA context(5) +any(c_combo_QA) U+17D2 U+17A2 U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+179B U+17D2 any(c_1st_combo_LO) U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+1798 U+17D2 any(c_1st_combo_MO) U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+179F U+17D2 U+1794 U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17C9 context(5) context(6) c prevent ស្ប៉ាំ from transforming to ស្ប៊ាំ +U+179F U+17D2 any(c_combo_SA) U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +any(c_combo_HA) U+17D2 U+17A0 U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+17A2 U+17D2 U+1784 U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) +U+17A2 U+17D2 U+179C U+17C9 U+17B6 U+17C6 > context(1) context(2) context(3) U+17CA context(5) context(6) + +c U+17B6 U+17BB and U+17C6 in that order preceeded by any first series consonant (cluster) are transformed to U+17CA U+17B6 and U+17C6 + +any(shiftable_c_1st) U+17B6 U+17BB U+17C6 > context(1) U+17CA context(2) context(4) +any(shiftable_c_1st) U+17BB U+17C6 U+17B6 > context(1) U+17CA context(4) context(3) + +any(c_combo_QA) U+17D2 U+17A2 U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +any(c_combo_QA) U+17D2 U+17A2 U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+179B U+17D2 any(c_1st_combo_LO) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+179B U+17D2 any(c_1st_combo_LO) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+1798 U+17D2 any(c_1st_combo_MO) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+179F U+17D2 any(c_combo_SA) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+179F U+17D2 any(c_combo_SA) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +any(c_combo_HA) U+17D2 U+17A0 U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +any(c_combo_HA) U+17D2 U+17A0 U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+17A2 U+17D2 U+1784 U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+17A2 U+17D2 U+1784 U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(6) context(5) + +U+17A2 U+17D2 U+179C U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17CA context(4) context(6) +U+17A2 U+17D2 U+179C U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17CA context(4) context(6) + +c U+17B6 U+17BB and U+17C6 in that order preceeded by any second series consonant (cluster) are transformed to U+17C9 U+17B6 and U+17C6 + +any(shiftable_c_2nd_with_BA) U+17B6 U+17BB U+17C6 > context(1) U+17C9 context(2) context(4) +any(shiftable_c_2nd_with_BA) U+17BB U+17C6 U+17B6 > context(1) U+17C9 context(4) context(3) + +U+179B U+17D2 any(c_2nd_combo_LO) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17C9 context(4) context(6) +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17C9 context(6) context(5) + +U+1798 U+17D2 any(c_2nd_combo_MO) U+17B6 U+17BB U+17C6 > context(1) context(2) context(3) U+17C9 context(4) context(6) +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB U+17C6 U+17B6 > context(1) context(2) context(3) U+17C9 context(6) context(5) + +c េុី/ុេី/៉េី > ៊ើ + +any(shiftable_c_1st) U+17C1 U+17BB U+17B8 > context(1) U+17CA U+17BE c cancel out by vowel rotation +any(shiftable_c_1st) U+17BB U+17C1 U+17B8 > context(1) U+17CA U+17BE c cancel out by vowel rotation +any(shiftable_c_1st) U+17C9 U+17C1 U+17B8 > context(1) U+17CA U+17BE + +any(c_combo_QA) U+17D2 U+17A2 U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +any(c_combo_QA) U+17D2 U+17A2 U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +any(c_combo_QA) U+17D2 U+17A2 U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+179B U+17D2 any(c_1st_combo_LO) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+179B U+17D2 any(c_1st_combo_LO) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+179B U+17D2 any(c_1st_combo_LO) U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+1798 U+17D2 any(c_1st_combo_MO) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+1798 U+17D2 any(c_1st_combo_MO) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+1798 U+17D2 any(c_1st_combo_MO) U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+179F U+17D2 any(c_combo_SA) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+179F U+17D2 any(c_combo_SA) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+179F U+17D2 any(c_combo_SA) U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +any(c_combo_HA) U+17D2 U+17A0 U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +any(c_combo_HA) U+17D2 U+17A0 U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +any(c_combo_HA) U+17D2 U+17A0 U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+17A2 U+17D2 U+1784 U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+17A2 U+17D2 U+1784 U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+17A2 U+17D2 U+1784 U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +U+17A2 U+17D2 U+179C U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+17A2 U+17D2 U+179C U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE c cancel out by vowel rotation +U+17A2 U+17D2 U+179C U+17C9 U+17C1 U+17B8 > context(1) context(2) context(3) U+17CA U+17BE + +c េុី/ុេី/៊េី > ៉ើ + +any(shiftable_c_2nd) U+17C1 U+17BB U+17B8 > context(1) U+17C9 U+17BE c cancel out by vowel rotation +any(shiftable_c_2nd) U+17BB U+17C1 U+17B8 > context(1) U+17C9 U+17BE c cancel out by vowel rotation +any(shiftable_c_2nd) U+17CA U+17C1 U+17B8 > context(1) U+17C9 U+17BE + +U+179B U+17D2 any(c_2nd_combo_LO) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE c cancel out by vowel rotation +U+179B U+17D2 any(c_2nd_combo_LO) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE c cancel out by vowel rotation +U+179B U+17D2 any(c_2nd_combo_LO) U+17CA U+17C1 U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE + +U+1798 U+17D2 any(c_2nd_combo_MO) U+17C1 U+17BB U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE c cancel out by vowel rotation +U+1798 U+17D2 any(c_2nd_combo_MO) U+17BB U+17C1 U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE c cancel out by vowel rotation +U+1798 U+17D2 any(c_2nd_combo_MO) U+17CA U+17C1 U+17B8 > context(1) context(2) context(3) U+17C9 U+17BE + +c place Robat after a base before any vowel + +any(c_out) any(v_gen) U+17CC > context(1) context(3) context(2) + +c Use appropriate identical subscript in two separate contexts. (Case #8) + +U+178E U+17D2 U+178F > context(1) context(2) U+178A +U+1793 U+17D2 U+178A > context(1) context(2) U+178F + +c BONUSES​(note that these combinations are invalid and they can't be found in the CN dictionary 1967 nor RH 1997, but users think they are) + +U+1791 U+17D2 U+1794 > U+17A1 c ទ្ប transforms to ឡ + +U+1794 U+17D2 U+1789 > U+17AB c ប្ញ transforms to ឫ +U+17AB U+17BB > U+17AC c ឫុ transforms to ឬ + +U+17AD U+17B6 > U+1789 c ឭា transforms to ញ +U+17AE U+17B6 > U+1789 c ឮា transforms to ញ + +U+1796 U+17D2 U+1789 > U+17AD c ព្ញ transforms to ឭ +U+17AD U+17BB > U+17AE c ឭុ transforms to ឮ + +U+1796 U+17D2 U+178B > U+17B0 c ព្ឋ transforms to ឰ + +U+17A7 U+17B7 > U+17B1 c ឧិ transforms to ឱ +U+17A7 U+17CC > U+17B1 c ឧ៌ transforms to ឱ +U+17A7 U+17CD > U+17B1 c ឧ៍ transforms to ឱ + +c U+17D4 U+179B U+17D4 > U+17D8 c ។ល។ transforms to U+17D8 + +U+178A U+17D2 U+1792 > U+178A U+17D2 U+178B c ដ្ធ > ដ្ឋ +U+1791 U+17D2 U+178B > U+1791 U+17D2 U+1792 c ទ្ឋ > ទ្ធ + +c additional rules + +U+1796 U+1793 U+17D2 U+178B > context(1) context(2) context(3) U+1792 c ពន្ឋ > ពន្ធ +U+1796 U+17D0 U+1793 U+17D2 U+178B > context(1) context(2) context(3) context(4) U+1792 c ព័ន្ឋ > ព័ន្ធ + + +U+17AA U+17D2 U+1799 > U+17B1 context(2) context(3) c ឪ្យ > ឱ្យ +U+17B3 U+17D2 U+1799 > U+17B1 context(2) context(3) c ឳ្យ > ឱ្យ + +U+1789 U+17D2 U+179C > U+1796 context(2) context(3) U+17B6 c ញ្វ (as in សញ្វវុធ) > ព្វា as in សញ្វវុធ + +U+17D2 U+1799 U+17C1 U+17BA > U+17BF c េ្យឺ > ឿ +U+17D2 U+1799 U+17C1 U+17B9 > U+17BF c េ្យឹ > ឿ +U+17D2 U+1799 U+17C1 U+17B8 > U+17BF c េ្យី > ឿ + +U+17D2 U+1799 U+17D2 any(c_out) U+17C1 U+17BA > context(3) context(4) U+17BF c គ្រេ្យឺង > គ្រឿង +U+17D2 U+1799 U+17D2 any(c_out) U+17C1 U+17B9 > context(3) context(4) U+17BF c គ្រេ្យឹង > គ្រឿង +U+17D2 U+1799 U+17D2 any(c_out) U+17C1 U+17B8 > context(3) context(4) U+17BF c គ្រេ្យីង > គ្រឿង + +c In everyday practice, both 'regular space' and 'no-break space' are not used before punctuation, i.e. ។ ! etc. +c An annoying issue of having line broken up at the end of the line dropping the punctuation (។, ! and also ៗ) to the next line. +c It may be helpful to include a rule where a 'Zero Width No-Break Space' should be output together with those punct. +c ref: https://www.unicode.org/L2/L2020/20008-core-text.pdf +c ref: https://www.unicode.org/versions/Unicode12.0.0/ch23.pdf#G12985 +c ref: https://www.compart.com/en/unicode/U+FEFF + +c EOF diff --git a/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kvks b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kvks new file mode 100644 index 0000000000..e9c38a464d --- /dev/null +++ b/developer/src/kmc-kmw/test/fixtures/khmer_angkor.kvks @@ -0,0 +1,206 @@ + + +
+ 10.0 + khmer_angkor + + + +
+ + + ឞ + ឝ + ៈ + ឳ + ឨ + ឩ + ឰ + ឫ + ឦ + ឱ + ឯ + + + ៜ + + ៖ + ៙ + ៚ + + ៘ + ‌ + ‍ + ] + [ + / + . + ‘ + + + & + ’ + * + @ + \ + } + { + - + ÷ + : + , + ≈ + ; + < + # + > + × + $ + € +   + + + ៸ + ៰ + ៱ + ៲ + ៳ + ៴ + ៵ + ៶ + ៷ + ៹ + ᧿ + ᧾ + ᧪ + ᧫ + ᧶ + ᧵ + ᧬ + ᧷ + ᧥ + ᧸ + ᧡ + ᧻ + ᧹ + ᧮ + ᧢ + ᧯ + ᧰ + ᧦ + ᧱ + ᧤ + ᧭ + ᧣ + ᧧ + ᧠ + ᧺ + ᧲ + ᧳ + ᧴ + ᧩ + ᧨ + ᧼ + ᧽ + + + ​ + + + ឥ + ។ + + ០ + ១ + ២ + ៣ + ៤ + ៥ + ៦ + ៧ + ៨ + ៩ + + ឲ + + ឮ + ឪ + « + + ប + ច + ដ + + ថ + ង + ហ + + + ក + ល + ម + ន + + ផ + ឆ + រ + ស + ត + + វ + + ខ + យ + ឋ + + + + ! + + " + ៛ + % + + ( + ) + + = + + ៕ + ? + ៗ + + ព + ជ + ឌ + + ធ + អ + ះ + + ញ + គ + ឡ + + ណ + + ភ + ឈ + ឬ + + ទ + + + + ឃ + + ឍ + + + + ឭ + ឧ + » + + + +
diff --git a/developer/src/kmc-kmw/test/test-compiler-manual.ts b/developer/src/kmc-kmw/test/test-compiler-manual.ts new file mode 100644 index 0000000000..af2589b833 --- /dev/null +++ b/developer/src/kmc-kmw/test/test-compiler-manual.ts @@ -0,0 +1,49 @@ +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import fs from 'fs'; +import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; +import { Compiler } from '@keymanapp/kmc-kmn'; +import { KMX, KmxFileReader } from '@keymanapp/common-types'; +import { WriteCompiledKeyboard } from '../src/compiler/write-compiled-keyboard.js'; + +const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/'); +const fixturesDir = __dirname + '/../../test/fixtures/'; +const fixtureName = fixturesDir + 'khmer_angkor.js'; +const infile = fixturesDir + 'khmer_angkor.kmn'; +const outfile = fixturesDir + 'khmer_angkor.kmx'; // intermediate outfile +const testOutfile = fixturesDir + 'khmer_angkor.test.js'; + +if(fs.existsSync(testOutfile)) { + fs.unlinkSync(testOutfile); +} + +const callbacks = new TestCompilerCallbacks(); + +const kmxCompiler = new Compiler(); +if(!await kmxCompiler.init()) { + console.error('kmx compiler failed to init'); + process.exit(1); +} + +// TODO: runToMemory, add option to kmxCompiler to store debug-data for conversion to .js (e.g. store metadata, group readonly metadata, etc) +if(!kmxCompiler.run(infile, outfile, callbacks, { + shouldAddCompilerVersion: false, + saveDebug: true +})) { + callbacks.printMessages(); + process.exit(1); +} + +const reader = new KmxFileReader(); +const keyboard: KMX.KEYBOARD = reader.read(callbacks.loadFile(outfile)); + +const js = WriteCompiledKeyboard(callbacks, 'khmer_angkor', keyboard, true); + +callbacks.printMessages(); + +const fjs = fs.readFileSync(fixtureName, 'utf8'); +if(fjs !== js) { + fs.writeFileSync(testOutfile, js); + console.error('JS not equal'); + process.exit(1); +} diff --git a/developer/src/kmc-kmw/test/test-compiler.ts b/developer/src/kmc-kmw/test/test-compiler.ts new file mode 100644 index 0000000000..7fb0efd9ce --- /dev/null +++ b/developer/src/kmc-kmw/test/test-compiler.ts @@ -0,0 +1,55 @@ +import 'mocha'; +import { assert } from 'chai'; +// import sinonChai from 'sinon-chai'; +import { WriteCompiledKeyboard } from '../src/compiler/write-compiled-keyboard.js'; +import { dirname } from 'path'; +import { fileURLToPath } from 'url'; +import fs from 'fs'; +import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; +import { Compiler } from '@keymanapp/kmc-kmn'; +import { KMX, KmxFileReader } from '@keymanapp/common-types'; + +const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/'); +const fixturesDir = __dirname + '/../../test/fixtures/'; +//const baselineDir = __dirname + '/../../../../../common/test/keyboards/baseline/'; +// chai.use(sinonChai); + +describe('Compiler class', function() { + const callbacks = new TestCompilerCallbacks(); + + this.afterEach(function() { + callbacks.printMessages(); + callbacks.clear(); + }); + + it('should compile a basic keyboard', async function() { + // const compiler = new KeymanWebCompiler(callbacks, {addCompilerVersion: false, debug: true}); + + const fixtureName = fixturesDir + 'khmer_angkor.js'; + const infile = fixturesDir + 'khmer_angkor.kmn'; + const outfile = fixturesDir + 'khmer_angkor.kmx'; // intermediate outfile + const testOutfile = fixturesDir + 'khmer_angkor.test.js'; + + if(fs.existsSync(testOutfile)) { + fs.unlinkSync(testOutfile); + } + + const kmxCompiler = new Compiler(); + assert.isTrue(await kmxCompiler.init()); + + // TODO: runToMemory, add option to kmxCompiler to store debug-data for conversion to .js (e.g. store metadata, group readonly metadata, etc) + assert.isTrue(kmxCompiler.run(infile, outfile, callbacks)); + + const reader = new KmxFileReader(); + const keyboard: KMX.KEYBOARD = reader.read(callbacks.loadFile(outfile)); + + const js = WriteCompiledKeyboard(callbacks, 'khmer_angkor', keyboard, true); + // const js = compiler.compile('khmer_angkor', keyboard); + + const fjs = fs.readFileSync(fixtureName, 'utf8'); + if(fjs !== js) { + fs.writeFileSync(testOutfile, js); + assert.fail('JS not equal'); + } + }); +}); \ No newline at end of file diff --git a/developer/src/kmc-kmw/test/tsconfig.json b/developer/src/kmc-kmw/test/tsconfig.json new file mode 100644 index 0000000000..abdb3a7cfe --- /dev/null +++ b/developer/src/kmc-kmw/test/tsconfig.json @@ -0,0 +1,25 @@ +{ + "extends": "../../kmc/tsconfig.kmc-base.json", + + "compilerOptions": { + "rootDir": ".", + "rootDirs": ["./", "../src/"], + "outDir": "../build/test", + "baseUrl": ".", + "allowSyntheticDefaultImports": true, // for chai + "paths": { + "@keymanapp/common-types": ["../../../../common/web/types/src/main"], + "@keymanapp/developer-test-helpers": ["../../common/web/test-helpers/index"], + "@keymanapp/kmc-kmn": ["../../kmc-kmn/src/main"], + }, + }, + "include": [ + "**/test-*.ts" + ], + "references": [ + { "path": "../../../../common/web/types/" }, + { "path": "../../kmc-kmn/" }, + { "path": "../../common/web/test-helpers/" }, + { "path": "../" } + ] +} \ No newline at end of file diff --git a/developer/src/kmc-kmw/tsconfig.json b/developer/src/kmc-kmw/tsconfig.json index a9dcdbbb2a..fb2abd93e3 100644 --- a/developer/src/kmc-kmw/tsconfig.json +++ b/developer/src/kmc-kmw/tsconfig.json @@ -16,9 +16,9 @@ }, "include": [ "src/**/*.ts" - ], +, "src/compiler/__keymanweb-compiler.ts.tmp" ], "references": [ - { "path": "../../../common/web/keyman-version/tsconfig.esm.json" }, + // { "path": "../../../common/web/keyman-version/tsconfig.esm.json" }, { "path": "../../../common/web/types/" }, { "path": "../../../core/include/ldml/"}, ] From d2581ae4a88e0f9a131650b17c85cc2839fb5034 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 5 May 2023 09:14:15 +0700 Subject: [PATCH 06/21] feat(developer): 'working' kmw compiler --- .../keyman-touch-layout-file-writer.ts | 31 +- common/web/types/src/kmx/kmx-file-reader.ts | 54 +++- common/web/types/src/kmx/kmx.ts | 18 +- common/web/types/src/kvk/visual-keyboard.ts | 1 + common/web/types/src/main.ts | 2 +- .../src/kmc-kmn/src/compiler/compiler.ts | 12 +- developer/src/kmc-kmw/build.sh | 1 + developer/src/kmc-kmw/package.json | 4 +- .../src/compiler/javascript-strings.ts | 4 +- .../src/compiler/keymanweb-key-codes.ts | 271 +++++++++++++++++ .../src/compiler/validate-layout-file.ts | 280 ++++++++++++++++++ .../src/compiler/visual-keyboard-compiler.ts | 163 ++++++++++ .../src/compiler/write-compiled-keyboard.ts | 86 +++--- .../src/kmc-kmw/test/test-compiler-manual.ts | 12 +- developer/src/kmc-kmw/test/test-compiler.ts | 26 +- developer/src/kmc-kmw/test/tsconfig.json | 3 +- developer/src/kmc-kmw/test/util.ts | 19 ++ developer/src/kmc-kmw/tsconfig.json | 9 +- developer/src/kmcmpdll/Compiler.cpp | 2 +- developer/src/kmcmplib/include/kmcmplibapi.h | 3 +- developer/src/kmcmplib/src/Compiler.cpp | 15 +- .../src/kmcmplib/src/CompilerInterfaces.cpp | 9 +- developer/src/kmcmplib/tests/api-test.cpp | 2 +- developer/src/kmcmplib/tests/kmcompxtest.cpp | 2 +- 24 files changed, 938 insertions(+), 91 deletions(-) create mode 100644 developer/src/kmc-kmw/src/compiler/keymanweb-key-codes.ts create mode 100644 developer/src/kmc-kmw/src/compiler/validate-layout-file.ts create mode 100644 developer/src/kmc-kmw/src/compiler/visual-keyboard-compiler.ts create mode 100644 developer/src/kmc-kmw/test/util.ts diff --git a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts b/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts index a86ed0441f..6ee01b7f8e 100644 --- a/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts +++ b/common/web/types/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts @@ -17,12 +17,19 @@ export class TouchLayoutFileWriter { * @param source TouchLayoutFile * @returns Uint8Array, the .keyman-touch-layout file */ - write(source: TouchLayoutFile): Uint8Array { - const output = JSON.stringify(source, null, this.options?.formatted ? 2 : undefined); + public write(source: TouchLayoutFile): Uint8Array { + const output = this.toJSONString(source); const encoder = new TextEncoder(); return encoder.encode(output); } + /** + * Gets the output as a JSON string + */ + public toJSONString(source: TouchLayoutFile): string { + return JSON.stringify(source, null, this.options?.formatted ? 2 : undefined); + } + /** * Compiles the touch layout file into a KeymanWeb-compatible JSON-style * object string. In the future, this may be optimized to remove unnecessary @@ -31,7 +38,11 @@ export class TouchLayoutFileWriter { * @param source * @returns string */ - compile(source: TouchLayoutFile): string { + public compile(source: TouchLayoutFile): string { + return this.toJSONString(this.fixup(source)); + } + + public fixup(source: TouchLayoutFile): TouchLayoutFile { // Deep copy the source source = JSON.parse(JSON.stringify(source)); @@ -40,13 +51,23 @@ export class TouchLayoutFileWriter { const fixupKey = (key: TouchLayoutKey | TouchLayoutSubKey) => { if(Object.hasOwn(key, 'pad')) (key.pad as any) = key.pad.toString(); - if(Object.hasOwn(key, 'sp')) (key.sp as any) = key.sp.toString(); + if(Object.hasOwn(key, 'sp')) { + if(key.sp == 0) { + delete key.sp; + } + else { + (key.sp as any) = key.sp.toString(); + } + } if(Object.hasOwn(key, 'width')) (key.width as any) = key.width.toString(); + if(Object.hasOwn(key, 'text') && key.text === '') delete key.text; }; const fixupPlatform = (platform: TouchLayoutPlatform) => { for(let layer of platform.layer) { for(let row of layer.row) { + // this matches the old spec for touch layout files + (row.id as any) = row.id.toString(); for(let key of row.key) { fixupKey(key); if(key.sk) { @@ -79,6 +100,6 @@ export class TouchLayoutFileWriter { fixupPlatform(source.tablet); } - return JSON.stringify(source, null, this.options?.formatted ? 2 : undefined); + return source; } }; \ No newline at end of file diff --git a/common/web/types/src/kmx/kmx-file-reader.ts b/common/web/types/src/kmx/kmx-file-reader.ts index 824e56c71d..45131ade77 100644 --- a/common/web/types/src/kmx/kmx-file-reader.ts +++ b/common/web/types/src/kmx/kmx-file-reader.ts @@ -13,11 +13,42 @@ export class KmxFileReader { return this.rString.fromBuffer(source.slice(offset)); } + private processSystemStore(store: STORE, result: KEYBOARD) { + switch(store.dwSystemID) { + case KMXFile.TSS_MNEMONIC: + result.isMnemonic = store.dpString == '1'; + break; + case KMXFile.TSS_KEYBOARDVERSION: + result.keyboardVersion = store.dpString; + break; + case KMXFile.TSS_BEGIN_NEWCONTEXT: + if(store.dpString.length == 3 && store.dpString.charCodeAt(0) == 0xFFFF && store.dpString.charCodeAt(1) == KMXFile.CODE_USE) { + result.startGroup.newContext = store.dpString.charCodeAt(2) - 1; + } + else { + // TODO: error + return false; + } + break; + case KMXFile.TSS_BEGIN_POSTKEYSTROKE: + if(store.dpString.length == 3 && store.dpString.charCodeAt(0) == 0xFFFF && store.dpString.charCodeAt(1) == KMXFile.CODE_USE) { + result.startGroup.postKeystroke = store.dpString.charCodeAt(2) - 1; + } + else { + // TODO: error + return false; + } + break; + } + return true; + } + public read(source: Uint8Array): KEYBOARD { let binaryKeyboard: BUILDER_COMP_KEYBOARD; let kmx = new KMXFile(); binaryKeyboard = kmx.COMP_KEYBOARD.fromBuffer(source); if(binaryKeyboard.dwIdentifier != KMXFile.FILEID_COMPILED) { + // TODO: error return null; } @@ -25,14 +56,17 @@ export class KmxFileReader { result.fileVersion = binaryKeyboard.dwFileVersion; result.flags = binaryKeyboard.dwFlags; result.hotkey = binaryKeyboard.dwHotKey; - result.keyboardVersion = '0'; //TODO result.startGroup = { - ansi: binaryKeyboard.StartGroup_ANSI, - unicode: binaryKeyboard.StartGroup_Unicode, + ansi: binaryKeyboard.StartGroup_ANSI == 0xFFFFFFFF ? -1 : binaryKeyboard.StartGroup_ANSI, + unicode: binaryKeyboard.StartGroup_Unicode == 0xFFFFFFFF ? -1 : binaryKeyboard.StartGroup_Unicode, newContext: -1, //TODO postKeystroke: -1 // TODO } + // Informative data + result.keyboardVersion = ''; + result.isMnemonic = false; + let offset = binaryKeyboard.dpStoreArray; for(let i = 0; i < binaryKeyboard.cxStoreArray; i++) { let binaryStore = kmx.COMP_STORE.fromBuffer(source.slice(offset)); @@ -41,6 +75,11 @@ export class KmxFileReader { store.dpName = this.readString(source, binaryStore.dpName); store.dpString = this.readString(source, binaryStore.dpString); result.stores.push(store); + + if(!this.processSystemStore(store, result)) { + return null; + } + offset += KMXFile.COMP_STORE_SIZE; } @@ -73,6 +112,15 @@ export class KmxFileReader { // TODO: KMXPlusFile + // Validate startGroup offsets + let gp: keyof KEYBOARD['startGroup']; + for(gp in result.startGroup) { + if(result.startGroup[gp] < -1 || result.startGroup[gp] >= result.groups.length) { + // TODO: error + return null; + } + } + return result; } }; \ No newline at end of file diff --git a/common/web/types/src/kmx/kmx.ts b/common/web/types/src/kmx/kmx.ts index cb7af49480..17e8b3749f 100644 --- a/common/web/types/src/kmx/kmx.ts +++ b/common/web/types/src/kmx/kmx.ts @@ -9,14 +9,13 @@ import * as r from 'restructure'; export class KEYBOARD { fileVersion?: number; // dwFileVersion (TSS_FILEVERSION) - keyboardVersion?: string; // version (TSS_KEYBOARDVERSION) startGroup: { - ansi: number; - unicode: number; - newContext: number; // TSS_BEGIN_NEWCONTEXT - postKeystroke: number; // TSS_BEGIN_POSTKEYSTROKE - } = {ansi:0xFFFFFFFF, unicode:0xFFFFFFFF, newContext:0xFFFFFFFF, postKeystroke:0xFFFFFFFF}; + ansi: number; // from COMP_KEYBOARD + unicode: number; // from COMP_KEYBOARD + newContext: number; // from TSS_BEGIN_NEWCONTEXT store + postKeystroke: number; // from TSS_BEGIN_POSTKEYSTROKE store + } = {ansi:-1, unicode:-1, newContext:-1, postKeystroke:-1}; flags?: number; hotkey?: number; @@ -24,6 +23,13 @@ export class KEYBOARD { //bitmap: groups: GROUP[] = []; stores: STORE[] = []; + + // Following values are extracted from stores[] but are + // informative only + + keyboardVersion?: string; // version (TSS_KEYBOARDVERSION) + isMnemonic: boolean; // TSS_MNEMONICLAYOUT store + }; export class STORE { diff --git a/common/web/types/src/kvk/visual-keyboard.ts b/common/web/types/src/kvk/visual-keyboard.ts index c1f1d5d7e9..4965a39b52 100644 --- a/common/web/types/src/kvk/visual-keyboard.ts +++ b/common/web/types/src/kvk/visual-keyboard.ts @@ -26,6 +26,7 @@ export class VisualKeyboardFont { name?: string; size?: number; color?: number; // unused + style?: string; // TODO: figure out style vs color issues }; export { BUILDER_KVK_KEY_FLAGS as VisualKeyboardKeyFlags } from "./kvk-file.js"; diff --git a/common/web/types/src/main.ts b/common/web/types/src/main.ts index 4e77550384..03ea2e8cd6 100644 --- a/common/web/types/src/main.ts +++ b/common/web/types/src/main.ts @@ -7,7 +7,7 @@ export { KmxFileReader } from './kmx/kmx-file-reader.js'; export * as VisualKeyboard from './kvk/visual-keyboard.js'; export { default as KMXPlusBuilder} from './kmx/kmx-plus-builder/kmx-plus-builder.js'; export { default as KvkFileReader } from './kvk/kvk-file-reader.js'; -export { default as KvksFileReader } from './kvk/kvks-file-reader.js'; +export { default as KvksFileReader, KVKSParseError } from './kvk/kvks-file-reader.js'; export { default as KvkFileWriter } from './kvk/kvk-file-writer.js'; export * as KvkFile from './kvk/kvk-file.js'; export * as KvksFile from './kvk/kvk-file.js'; diff --git a/developer/src/kmc-kmn/src/compiler/compiler.ts b/developer/src/kmc-kmn/src/compiler/compiler.ts index 2f83e83aee..5ca3f9a942 100644 --- a/developer/src/kmc-kmn/src/compiler/compiler.ts +++ b/developer/src/kmc-kmn/src/compiler/compiler.ts @@ -31,13 +31,15 @@ export interface CompilerOptions { saveDebug?: boolean; compilerWarningsAsErrors?: boolean; warnDeprecatedCode?: boolean; + target?: 'kmx' | 'js'; }; const baseOptions: CompilerOptions = { shouldAddCompilerVersion: true, saveDebug: true, compilerWarningsAsErrors: false, - warnDeprecatedCode: true + warnDeprecatedCode: true, + target: 'kmx' }; /** @@ -106,7 +108,7 @@ export class KmnCompiler { this.callbacks.reportMessage(CompilerMessages.Fatal_MissingWasmModule({e})); return false; } - } + return this.verifyInitialized(); } @@ -145,6 +147,9 @@ export class KmnCompiler { } private runCompiler(infile: string, outfile: string, options: CompilerOptions): boolean { + const CKF_KEYMAN = 0; + const CKF_KEYMANWEB = 1; + try { if (!this.wasm.setCompilerOptions(options.shouldAddCompilerVersion ? 1 : 0)) { this.callbacks.reportMessage(CompilerMessages.Fatal_UnableToSetCompilerOptions()); @@ -155,7 +160,8 @@ export class KmnCompiler { options.saveDebug ? 1 : 0, options.compilerWarningsAsErrors ? 1 : 0, options.warnDeprecatedCode ? 1 : 0, - this.callbackName); + this.callbackName, + options.target == 'js' ? CKF_KEYMANWEB : CKF_KEYMAN); } catch(e) { this.callbacks.reportMessage(CompilerMessages.Fatal_UnexpectedException({e:e})); return false; diff --git a/developer/src/kmc-kmw/build.sh b/developer/src/kmc-kmw/build.sh index 684f5f7911..be180cc725 100755 --- a/developer/src/kmc-kmw/build.sh +++ b/developer/src/kmc-kmw/build.sh @@ -19,6 +19,7 @@ cd "$THIS_SCRIPT_PATH" builder_describe "Build Keyman kmc KMW Keyboard Compiler module" \ "@/common/web/keyman-version" \ "@/common/web/types" \ + "@/developer/src/kmc-kmn" \ "configure" \ "build" \ "clean" \ diff --git a/developer/src/kmc-kmw/package.json b/developer/src/kmc-kmw/package.json index e00a3c7e31..fc4448b87e 100644 --- a/developer/src/kmc-kmw/package.json +++ b/developer/src/kmc-kmw/package.json @@ -24,6 +24,7 @@ }, "dependencies": { "@keymanapp/common-types": "*", + "@keymanapp/kmc-kmn": "*", "ajv": "^8.11.0", "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", "semver": "^7.3.7", @@ -40,8 +41,7 @@ "chalk": "^2.4.2", "mocha": "^8.4.0", "ts-node": "^9.1.1", - "typescript": "^4.9.5", - "@keymanapp/kmc-kmn": "*" + "typescript": "^4.9.5" }, "mocha": { "spec": "build/test/**/test-*.js", diff --git a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts index b4ae08829d..2504781b9b 100644 --- a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts +++ b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts @@ -324,7 +324,7 @@ export function JavaScript_ShiftAsString(fkp: KMX.KEY, FMnemonic: boolean): stri return ' '+FormatModifierAsBitflags(JavaScript_Shift(fkp, FMnemonic)); } -const VKeyNames = [ // from vkeys.h +export const VKeyNames = [ // from vkeys.h // Key Codes "K_?00", // &H0 "K_LBUTTON", // &H1 @@ -671,7 +671,7 @@ function FormatKeyForErrorMessage(fkp: KMX.KEY, FMnemonic: boolean): string { return result; } -function JavaScript_Key(fkp: KMX.KEY, FMnemonic: boolean): number { +export function JavaScript_Key(fkp: KMX.KEY, FMnemonic: boolean): number { let Result: number; if(!FMnemonic) { if(fkp.ShiftFlags & KMX.KMXFile.ISVIRTUALKEY) { diff --git a/developer/src/kmc-kmw/src/compiler/keymanweb-key-codes.ts b/developer/src/kmc-kmw/src/compiler/keymanweb-key-codes.ts new file mode 100644 index 0000000000..98e609d747 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/keymanweb-key-codes.ts @@ -0,0 +1,271 @@ +export const + CKeymanWebKeyCodes: number[] = [ + 0xFF, // L"K_?00", // &H0 + 0xFF, // L"K_LBUTTON", // &H1 + 0xFF, // L"K_RBUTTON", // &H2 + 0xFF, // L"K_CANCEL", // &H3 + 0xFF, // L"K_MBUTTON", // &H4 + 0xFF, // L"K_?05", // &H5 + 0xFF, // L"K_?06", // &H6 + 0xFF, // L"K_?07", // &H7 + 0xFF, // L"K_BKSP", // &H8 + 0xFF, // L"K_TAB", // &H9 + 0xFF, // L"K_?0A", // &HA + 0xFF, // L"K_?0B", // &HB + 0xFF, // L"K_KP5", // &HC + 0xFF, // L"K_ENTER", // &HD + 0xFF, // L"K_?0E", // &HE + 0xFF, // L"K_?0F", // &HF + 0xFF, // L"K_SHIFT", // &H10 + 0xFF, // L"K_CONTROL", // &H11 + 0xFF, // L"K_ALT", // &H12 + 0xFF, // L"K_PAUSE", // &H13 + 0xFF, // L"K_CAPS", // &H14 + 0xFF, // L"K_KANJI?15", // &H15 + 0xFF, // L"K_KANJI?16", // &H16 + 0xFF, // L"K_KANJI?17", // &H17 + 0xFF, // L"K_KANJI?18", // &H18 + 0xFF, // L"K_KANJI?19", // &H19 + 0xFF, // L"K_?1A", // &H1A + 0xFF, // L"K_ESC", // &H1B + 0xFF, // L"K_KANJI?1C", // &H1C + 0xFF, // L"K_KANJI?1D", // &H1D + 0xFF, // L"K_KANJI?1E", // &H1E + 0xFF, // L"K_KANJI?1F", // &H1F + 0x40, // L"K_SPACE", // &H20 + 0xFF, // L"K_PGUP", // &H21 + 0xFF, // L"K_PGDN", // &H22 + 0xFF, // L"K_END", // &H23 + 0xFF, // L"K_HOME", // &H24 + 0xFF, // L"K_LEFT", // &H25 + 0xFF, // L"K_UP", // &H26 + 0xFF, // L"K_RIGHT", // &H27 + 0xFF, // L"K_DOWN", // &H28 + 0xFF, // L"K_SEL", // &H29 + 0xFF, // L"K_PRINT", // &H2A + 0xFF, // L"K_EXEC", // &H2B + 0xFF, // L"K_PRTSCN", // &H2C + 0xFF, // L"K_INS", // &H2D + 0xFF, // L"K_DEL", // &H2E + 0xFF, // L"K_HELP", // &H2F + 0x0A, // L"K_0", // &H30 + 0x01, // L"K_1", // &H31 + 0x02, // L"K_2", // &H32 + 0x03, // L"K_3", // &H33 + 0x04, // L"K_4", // &H34 + 0x05, // L"K_5", // &H35 + 0x06, // L"K_6", // &H36 + 0x07, // L"K_7", // &H37 + 0x08, // L"K_8", // &H38 + 0x09, // L"K_9", // &H39 + 0xFF, // L"K_?3A", // &H3A + 0xFF, // L"K_?3B", // &H3B + 0xFF, // L"K_?3C", // &H3C + 0xFF, // L"K_?3D", // &H3D + 0xFF, // L"K_?3E", // &H3E + 0xFF, // L"K_?3F", // &H3F + 0xFF, // L"K_?40", // &H40 + + 0x20, // L"K_A", // &H41 + 0x35, // L"K_B", // &H42 + 0x33, // L"K_C", // &H43 + 0x22, // L"K_D", // &H44 + 0x12, // L"K_E", // &H45 + 0x23, // L"K_F", // &H46 + 0x24, // L"K_G", // &H47 + 0x25, // L"K_H", // &H48 + 0x17, // L"K_I", // &H49 + 0x26, // L"K_J", // &H4A + 0x27, // L"K_K", // &H4B + 0x28, // L"K_L", // &H4C + 0x37, // L"K_M", // &H4D + 0x36, // L"K_N", // &H4E + 0x18, // L"K_O", // &H4F + 0x19, // L"K_P", // &H50 + 0x10, // L"K_Q", // &H51 + 0x13, // L"K_R", // &H52 + 0x21, // L"K_S", // &H53 + 0x14, // L"K_T", // &H54 + 0x16, // L"K_U", // &H55 + 0x34, // L"K_V", // &H56 + 0x11, // L"K_W", // &H57 + 0x32, // L"K_X", // &H58 + 0x15, // L"K_Y", // &H59 + 0x31, // L"K_Z", // &H5A + 0xFF, // L"K_?5B", // &H5B + 0xFF, // L"K_?5C", // &H5C + 0xFF, // L"K_?5D", // &H5D + 0xFF, // L"K_?5E", // &H5E + 0xFF, // L"K_?5F", // &H5F + 0xFF, // L"K_NP0", // &H60 + 0xFF, // L"K_NP1", // &H61 + 0xFF, // L"K_NP2", // &H62 + 0xFF, // L"K_NP3", // &H63 + 0xFF, // L"K_NP4", // &H64 + 0xFF, // L"K_NP5", // &H65 + 0xFF, // L"K_NP6", // &H66 + 0xFF, // L"K_NP7", // &H67 + 0xFF, // L"K_NP8", // &H68 + 0xFF, // L"K_NP9", // &H69 + 0xFF, // L"K_NPSTAR", // &H6A + 0xFF, // L"K_NPPLUS", // &H6B + 0xFF, // L"K_SEPARATOR", // &H6C + 0xFF, // L"K_NPMINUS", // &H6D + 0xFF, // L"K_NPDOT", // &H6E + 0xFF, // L"K_NPSLASH", // &H6F + 0xFF, // L"K_F1", // &H70 + 0xFF, // L"K_F2", // &H71 + 0xFF, // L"K_F3", // &H72 + 0xFF, // L"K_F4", // &H73 + 0xFF, // L"K_F5", // &H74 + 0xFF, // L"K_F6", // &H75 + 0xFF, // L"K_F7", // &H76 + 0xFF, // L"K_F8", // &H77 + 0xFF, // L"K_F9", // &H78 + 0xFF, // L"K_F10", // &H79 + 0xFF, // L"K_F11", // &H7A + 0xFF, // L"K_F12", // &H7B + 0xFF, // L"K_F13", // &H7C + 0xFF, // L"K_F14", // &H7D + 0xFF, // L"K_F15", // &H7E + 0xFF, // L"K_F16", // &H7F + 0xFF, // L"K_F17", // &H80 + 0xFF, // L"K_F18", // &H81 + 0xFF, // L"K_F19", // &H82 + 0xFF, // L"K_F20", // &H83 + 0xFF, // L"K_F21", // &H84 + 0xFF, // L"K_F22", // &H85 + 0xFF, // L"K_F23", // &H86 + 0xFF, // L"K_F24", // &H87 + + 0xFF, // L"K_?88", // &H88 + 0xFF, // L"K_?89", // &H89 + 0xFF, // L"K_?8A", // &H8A + 0xFF, // L"K_?8B", // &H8B + 0xFF, // L"K_?8C", // &H8C + 0xFF, // L"K_?8D", // &H8D + 0xFF, // L"K_?8E", // &H8E + 0xFF, // L"K_?8F", // &H8F + + 0xFF, // L"K_NUMLOCK", // &H90 + 0xFF, // L"K_SCROLL", // &H91 + + 0xFF, // L"K_?92", // &H92 + 0xFF, // L"K_?93", // &H93 + 0xFF, // L"K_?94", // &H94 + 0xFF, // L"K_?95", // &H95 + 0xFF, // L"K_?96", // &H96 + 0xFF, // L"K_?97", // &H97 + 0xFF, // L"K_?98", // &H98 + 0xFF, // L"K_?99", // &H99 + 0xFF, // L"K_?9A", // &H9A + 0xFF, // L"K_?9B", // &H9B + 0xFF, // L"K_?9C", // &H9C + 0xFF, // L"K_?9D", // &H9D + 0xFF, // L"K_?9E", // &H9E + 0xFF, // L"K_?9F", // &H9F + 0xFF, // L"K_?A0", // &HA0 + 0xFF, // L"K_?A1", // &HA1 + 0xFF, // L"K_?A2", // &HA2 + 0xFF, // L"K_?A3", // &HA3 + 0xFF, // L"K_?A4", // &HA4 + 0xFF, // L"K_?A5", // &HA5 + 0xFF, // L"K_?A6", // &HA6 + 0xFF, // L"K_?A7", // &HA7 + 0xFF, // L"K_?A8", // &HA8 + 0xFF, // L"K_?A9", // &HA9 + 0xFF, // L"K_?AA", // &HAA + 0xFF, // L"K_?AB", // &HAB + 0xFF, // L"K_?AC", // &HAC + 0xFF, // L"K_?AD", // &HAD + 0xFF, // L"K_?AE", // &HAE + 0xFF, // L"K_?AF", // &HAF + 0xFF, // L"K_?B0", // &HB0 + 0xFF, // L"K_?B1", // &HB1 + 0xFF, // L"K_?B2", // &HB2 + 0xFF, // L"K_?B3", // &HB3 + 0xFF, // L"K_?B4", // &HB4 + 0xFF, // L"K_?B5", // &HB5 + 0xFF, // L"K_?B6", // &HB6 + 0xFF, // L"K_?B7", // &HB7 + 0xFF, // L"K_?B8", // &HB8 + 0xFF, // L"K_?B9", // &HB9 + + 0x29, // L"K_COLON", // &HBA + 0x0C, // L"K_EQUAL", // &HBB + 0x38, // L"K_COMMA", // &HBC + 0x0B, // L"K_HYPHEN", // &HBD + 0x39, // L"K_PERIOD", // &HBE + 0x3A, // L"K_SLASH", // &HBF + 0x00, // L"K_BKQUOTE", // &HC0 + + 0x00, // L"K_?C1", // &HC1 + 0x00, // L"K_?C2", // &HC2 + 0x00, // L"K_?C3", // &HC3 + 0x00, // L"K_?C4", // &HC4 + 0x00, // L"K_?C5", // &HC5 + 0x00, // L"K_?C6", // &HC6 + 0x00, // L"K_?C7", // &HC7 + 0x00, // L"K_?C8", // &HC8 + 0x00, // L"K_?C9", // &HC9 + 0x00, // L"K_?CA", // &HCA + 0x00, // L"K_?CB", // &HCB + 0x00, // L"K_?CC", // &HCC + 0x00, // L"K_?CD", // &HCD + 0x00, // L"K_?CE", // &HCE + 0x00, // L"K_?CF", // &HCF + 0x00, // L"K_?D0", // &HD0 + 0x00, // L"K_?D1", // &HD1 + 0x00, // L"K_?D2", // &HD2 + 0x00, // L"K_?D3", // &HD3 + 0x00, // L"K_?D4", // &HD4 + 0x00, // L"K_?D5", // &HD5 + 0x00, // L"K_?D6", // &HD6 + 0x00, // L"K_?D7", // &HD7 + 0x00, // L"K_?D8", // &HD8 + 0x00, // L"K_?D9", // &HD9 + 0x00, // L"K_?DA", // &HDA + + 0x1A, // L"K_LBRKT", // &HDB + 0x1C, // L"K_BKSLASH", // &HDC + 0x1B, // L"K_RBRKT", // &HDD + 0x2A, // L"K_QUOTE", // &HDE + 0x00, // L"K_oDF", // &HDF + 0x00, // L"K_oE0", // &HE0 + 0x00, // L"K_oE1", // &HE1 + 0x30, // L"K_oE2", // &HE2 + 0x00, // L"K_oE3", // &HE3 + 0x00, // L"K_oE4", // &HE4 + + 0x00, // L"K_?E5", // &HE5 + + 0x00, // L"K_oE6", // &HE6 + + 0x00, // L"K_?E7", // &HE7 + 0x00, // L"K_?E8", // &HE8 + + 0x00, // L"K_oE9", // &HE9 + 0x00, // L"K_oEA", // &HEA + 0x00, // L"K_oEB", // &HEB + 0x00, // L"K_oEC", // &HEC + 0x00, // L"K_oED", // &HED + 0x00, // L"K_oEE", // &HEE + 0x00, // L"K_oEF", // &HEF + 0x00, // L"K_oF0", // &HF0 + 0x00, // L"K_oF1", // &HF1 + 0x00, // L"K_oF2", // &HF2 + 0x00, // L"K_oF3", // &HF3 + 0x00, // L"K_oF4", // &HF4 + 0x00, // L"K_oF5", // &HF5 + + 0x00, // L"K_?F6", // &HF6 + 0x00, // L"K_?F7", // &HF7 + 0x00, // L"K_?F8", // &HF8 + 0x00, // L"K_?F9", // &HF9 + 0x00, // L"K_?FA", // &HFA + 0x00, // L"K_?FB", // &HFB + 0x00, // L"K_?FC", // &HFC + 0x00, // L"K_?FD", // &HFD + 0x00, // L"K_?FE", // &HFE + 0x00 // L"K_?FF" // &HFF + ]; \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/validate-layout-file.ts b/developer/src/kmc-kmw/src/compiler/validate-layout-file.ts new file mode 100644 index 0000000000..30d6f660d9 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/validate-layout-file.ts @@ -0,0 +1,280 @@ +import { KMX, TouchLayout, TouchLayoutFileReader, TouchLayoutFileWriter } from "@keymanapp/common-types"; +import { callbacks, IsKeyboardVersion14OrLater, IsKeyboardVersion15OrLater } from "./compiler-globals.js"; +import { JavaScript_Key, VKeyNames } from "./javascript-strings.js"; + + +interface VLFOutput { + output: string; + result: boolean; +}; + +function IsValidUnicodeValue(ch: number): boolean { // I4198 + return ((ch >= 0x0020) && (ch <= 0x007F)) || + ((ch >= 0x00A0) && (ch <= 0x10FFFF)); +} + +enum TKeyIdType { Key_Invalid, Key_Constant, Key_Touch, Key_Unicode, Key_Unicode_Multi }; // I4142 + +function GetKeyIdUnicodeType(value: string): TKeyIdType { + let values = value.split('_'); + for(let v of values) { + if(!IsValidUnicodeValue(parseInt(v,16))) { + return TKeyIdType.Key_Invalid; + } + } + if(values.length > 1) { + return TKeyIdType.Key_Unicode_Multi; + } + return TKeyIdType.Key_Unicode; +} + +function KeyIdType(FId: string): TKeyIdType { // I4142 + FId = FId.toUpperCase(); + switch(FId.charAt(0)) { + case 'T': + return TKeyIdType.Key_Touch; + case 'U': + if(FId.startsWith('U_')) { + return GetKeyIdUnicodeType(FId.substring(2)); + } + default: + // Note: can't use indexOf because some VKeyNames are mixed case, e.g. K_oE2 + if(VKeyNames.find(key => key.toUpperCase() == FId)) { + return TKeyIdType.Key_Constant; + } + } + return TKeyIdType.Key_Invalid; +} + +enum TRequiredKey { K_LOPT, K_BKSP, K_ENTER }; // I4447 + +const + CRequiredKeys: TRequiredKey[] = [TRequiredKey.K_LOPT, TRequiredKey.K_BKSP, TRequiredKey.K_ENTER]; // I4447 + + // See also builder.js: specialCharacters; web/source/osk/oskKey.ts: specialCharacters +const + CSpecialText10: string = + '*Shift*\0*Enter*\0*Tab*\0*BkSp*\0*Menu*\0*Hide*\0*Alt*\0*Ctrl*\0*Caps*\0'+ + '*ABC*\0*abc*\0*123*\0*Symbol*\0*Currency*\0*Shifted*\0*AltGr*\0*TabLeft*', + + // these names were added in Keyman 14 + CSpecialText14: string = + '*LTREnter*\0*LTRBkSp*\0*RTLEnter*\0*RTLBkSp*\0*ShiftLock*\0*ShiftedLock*\0*ZWNJ*\0*ZWNJiOS*\0*ZWNJAndroid*', + CSpecialText14ZWNJ: string = + '*ZWNJ*\0*ZWNJiOS*\0*ZWNJAndroid*', + + CSpecialText14Map: string[][] = [ + ['*LTREnter*', '*Enter*'], + ['*LTRBkSp*', '*BkSp*'], + ['*RTLEnter*', '*Enter*'], + ['*RTLBkSp*', '*BkSp*'], + ['*ShiftLock*', '*Shift*'], + ['*ShiftedLock*', '*Shifted*'], + ['*ZWNJ*', '<|>'], + ['*ZWNJiOS*', '<|>'], + ['*ZWNJAndroid*', '<|>'] + ]; + +// TODO lifecycle + +function CheckKey(FPlatform: TouchLayout.TouchLayoutPlatform, + FId: string, FText: string, FNextLayer: string, FKeyType: TouchLayout.TouchLayoutKeySp, + FRequiredKeys: TRequiredKey[], FDictionary: string[]) { // I4119 + + // + // Check that each touch layer has K_LOPT, [K_ROPT,] K_BKSP, K_ENTER + // + + for(let key of CRequiredKeys) { + if(TRequiredKey[key].toLowerCase() == FId.toLowerCase()) { + FRequiredKeys.push(key); + break; + } + } + + // + // Check that each layer referenced exists + // + + if(typeof FNextLayer == 'string' && FNextLayer.length > 0) { + if(FPlatform.layer.find(l => l.id.toLowerCase() == FNextLayer.toLowerCase()) == undefined) { + // TODO: callbacks.reportMessage() ReportError(0, CWARN_TouchLayoutMissingLayer, 'Key "'+FId+'" on platform "'+FPlatform.Name+'", layer "'+FLayer.Id+'", platform "'+FPlatform.Name+'", references a missing layer "'+FNextLayer+'".'); + } + } + + // + // Check that the key has a valid id // I4142 + // + + if(FId.trim() == '') { + if(!(FKeyType in [TouchLayout.TouchLayoutKeySp.blank, TouchLayout.TouchLayoutKeySp.spacer]) && FNextLayer == '') { + // TODO: ReportError(0, CWARN_TouchLayoutUnidentifiedKey, 'A key on layer "'+FLayer.Id+'" has no identifier.'); + } + return; + } + + let FValid = KeyIdType(FId); + + if(FValid == TKeyIdType.Key_Invalid) { + // TODO: ReportError(0, CERR_TouchLayoutInvalidIdentifier, 'Key "'+FId+'" on "'+FPlatform.Name+'", layer "'+FLayer.Id+'" has an invalid identifier.'); + } + else if (FValid == TKeyIdType.Key_Unicode_Multi && !IsKeyboardVersion15OrLater()) { + // TODO: ReportError(0, CERR_TouchLayoutInvalidIdentifier, 'Key "'+FId+'" on "'+FPlatform.Name+'", layer "'+FLayer.Id+'" has a multi-part identifier which requires version 15.0 or newer.'); + } + + // + // Check that each custom key code has at least *a* rule associated with it + // + + if (FValid == TKeyIdType.Key_Touch && FNextLayer == '' && FKeyType in [TouchLayout.TouchLayoutKeySp.normal, TouchLayout.TouchLayoutKeySp.deadkey]) { + // Search for the key in the key dictionary - ignore K_LOPT, K_ROPT... + if(FDictionary.indexOf(FId) < 0) { + // TODO: ReportError(0, CWARN_TouchLayoutCustomKeyNotDefined, 'Key "'+FId+'" on layer "'+FLayer.Id+'", platform "'+FPlatform.Name+'", is a custom key but has no corresponding rule in the source.'); + } + } + + // + // Check that if the key has a *special* label, it is available in the target version + // + if(FText.startsWith('*') && FText.endsWith('*') && FText.length > 2) { + // Keyman versions before 14 do not support '*special*' labels on non-special keys. + // ZWNJ use, however, is safe because it will be transformed in function + // TransformSpecialKeys14 to '<|>', which does not require the custom OSK font. + if((CSpecialText10.includes(FText) || CSpecialText14.includes(FText)) && + !CSpecialText14ZWNJ.includes(FText) && + !IsKeyboardVersion14OrLater() && + !(FKeyType in [TouchLayout.TouchLayoutKeySp.special, TouchLayout.TouchLayoutKeySp.specialActive])) { + // TODO: ReportError(0, CWARN_TouchLayoutSpecialLabelOnNormalKey, + // Format('Key "%s" on layout "%s", platform "%s" does not have the key type "Special" or "Special (active)" but has the label "%s". This feature is only supported in Keyman 14 or later', [ + // FId, FLayer.Id, FPlatform.Name, FText + // ])); + } + } +} + +function CheckDictionaryKeyValidity(fk: KMX.KEYBOARD, FDictionary: string[]) { // I4142 + + // TODO: O(eeek) performance here + + for(let i = 0; i < FDictionary.length; i++) { + if(FDictionary[i] == '') { + continue; + } + + if(KeyIdType(FDictionary[i]) in [TKeyIdType.Key_Invalid, TKeyIdType.Key_Constant]) { + for(let fgp of fk.groups) { + if(fgp.fUsingKeys) { + for(let fkp of fgp.keys) { + if(JavaScript_Key(fkp, fk.isMnemonic) == i+256) { + // TODO: ReportError(fkp.Line, CERR_InvalidKeyCode, 'Invalid key identifier "'+FDictionary[i]+'"'); + } + } + } + } + } + } +} + +function TransformSpecialKeys14(FDebug: boolean, sLayoutFile: string): string { + // Rewrite Special key labels that are only supported in Keyman 14+ + // This code is a little ugly but effective. + if(!IsKeyboardVersion14OrLater()) { + for(let i = 0; i < CSpecialText14Map.length; i++) { + // Assumes the JSON output format will not change + if(FDebug) { + sLayoutFile = sLayoutFile.replace('"text": "'+CSpecialText14Map[i][0]+'"', '"text": this._v>13 ? "'+CSpecialText14Map[i][0]+'" : "'+CSpecialText14Map[i][1]+'"'); + } else { + sLayoutFile = sLayoutFile.replace('"text":"'+CSpecialText14Map[i][0]+'"', '"text":this._v>13?"'+CSpecialText14Map[i][0]+'":"'+CSpecialText14Map[i][1]+'"'); + } + } + } + return sLayoutFile; +} + +export function ValidateLayoutFile(fk: KMX.KEYBOARD, FDebug: boolean, sLayoutFile: string, sVKDictionary: string): VLFOutput { // I4060 // I4139 + +/* +var + FPlatform: TTouchLayoutPlatform; + FLayer: TTouchLayoutLayer; + FRow: TTouchLayoutRow; + FKey: TTouchLayoutKey; + FSubKey: TTouchLayoutSubKey; + FRequiredKeys: set of TRequiredKey; + FDictionary: TStringList; + FDirection: TTouchLayoutFlickDirection; + +*/ + + let FDictionary: string[] = sVKDictionary.split(/\s+/); + + CheckDictionaryKeyValidity(fk, FDictionary); // I4142 + + let reader = new TouchLayoutFileReader(); + let data = reader.read(callbacks.loadFile(sLayoutFile)); + if(!data) { + // TODO: ReportError(0, CERR_InvalidTouchLayoutFile, sMsg); + return {output:null, result: false}; + } + + let FTouchLayoutFont = ''; // I4872 + let pid: keyof TouchLayout.TouchLayoutFile; + for(pid in data) { + let platform = data[pid]; + + // Test that the font matches on all platforms // I4872 + + if(FTouchLayoutFont == '') { + FTouchLayoutFont = platform.font; + } + else if(platform.font.toLowerCase() != FTouchLayoutFont) { + // TODO: ReportError(0, CWARN_TouchLayoutFontShouldBeSameForAllPlatforms, 'The touch layout font should be the same for all platforms.'); + // TODO: why support multiple font values if it has to be the same across all platforms?! + } + + // Test that all required keys are present + for(let layer of platform.layer) { + let FRequiredKeys: TRequiredKey[] = []; + for(let row of layer.row) { + for(let key of row.key) { + CheckKey(platform, key.id, key.text, key.nextlayer, key.sp, FRequiredKeys, FDictionary); // I4119 + if(key.sk) { + for(let subkey of key.sk) { + CheckKey(platform, subkey.id, subkey.text, subkey.nextlayer, subkey.sp, FRequiredKeys, FDictionary); + } + } + let direction: keyof TouchLayout.TouchLayoutFlick; + if(key.flick) { + for(direction in key.flick) { + CheckKey(platform, key.flick[direction].id, key.flick[direction].text, + key.flick[direction].nextlayer, key.flick[direction].sp, FRequiredKeys, FDictionary); + } + } + + if(key.multitap) { + for(let subkey of key.multitap) { + CheckKey(platform, subkey.id, subkey.text, subkey.nextlayer, subkey.sp, FRequiredKeys, FDictionary); + } + } + } + } + + if(FRequiredKeys.length != CRequiredKeys.length) { + // TODO: ReportError(0, CWARN_TouchLayoutMissingRequiredKeys, 'Layer "'+FLayer.Id+'" on platform "'+FPlatform.Name+'" is missing the required key(s) '+RequiredKeysToString(CRequiredKeys-FRequiredKeys)+'.'); + } + } + } + + // If not debugging, then this strips out formatting for a big saving in file size + // This also normalises any values such as Pad or Width which should be strings + let writer = new TouchLayoutFileWriter({formatted: FDebug}); + + sLayoutFile = writer.compile(data); + + sLayoutFile = TransformSpecialKeys14(FDebug, sLayoutFile); + + return { + output: sLayoutFile, + result: true + } +} \ No newline at end of file diff --git a/developer/src/kmc-kmw/src/compiler/visual-keyboard-compiler.ts b/developer/src/kmc-kmw/src/compiler/visual-keyboard-compiler.ts new file mode 100644 index 0000000000..6dc7cf3178 --- /dev/null +++ b/developer/src/kmc-kmw/src/compiler/visual-keyboard-compiler.ts @@ -0,0 +1,163 @@ +import { KMX, KvkFile, VisualKeyboard } from "@keymanapp/common-types"; +import { FTabStop, nl } from "./compiler-globals.js"; +import { CKeymanWebKeyCodes } from "./keymanweb-key-codes.js"; +import { RequotedString } from "./write-compiled-keyboard.js"; + +interface VKFFResult { + result: string; + displayUnderling: boolean; +} + +export function VisualKeyboardFromFile(visualKeyboard: VisualKeyboard.VisualKeyboard, debug: boolean): VKFFResult { + let fbold = ''; // TODO 'bold ' if visualKeyboard.header.unicodeFont.style + let fitalic = ''; // TODO 'italic ' if visualKeyboard.header.unicodeFont.style + let f102 = visualKeyboard.header.flags & KvkFile.BUILDER_KVK_HEADER_FLAGS.kvkh102 ? '1' : '0'; + + let result = `{F:'${fbold}${fitalic} 1em "${RequotedString(visualKeyboard.header.unicodeFont.name)}"',K102:${f102}}` + + `;` + VisualKeyboardToKLS(visualKeyboard) + + ';' + BuildBKFromKLS(debug); + + return { + result: result, + // TODO: this can go in caller, later + displayUnderling: !!(visualKeyboard.header.flags & KvkFile.BUILDER_KVK_HEADER_FLAGS.kvkhDisplayUnderlying) + } +} + +function WideQuote(s: string): string { + let result = ''; + for(let i = 0; i < s.length; i++) { + if(s[i] == '"' || s[i] == '\\') { + result += '\\' + s[i]; + } else { + result += s[i]; + } + } + return result; +} + +function VkShiftStateToKmxShiftState(ShiftState: number): number { + + interface TVKToKMX { + VK: number; KMX: number; + } + + const Map: TVKToKMX[] = [ + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_SHIFT, KMX: KMX.KMXFile.K_SHIFTFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_CTRL, KMX: KMX.KMXFile.K_CTRLFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_ALT, KMX: KMX.KMXFile.K_ALTFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_LCTRL, KMX: KMX.KMXFile.LCTRLFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_RCTRL, KMX: KMX.KMXFile.RCTRLFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_LALT, KMX: KMX.KMXFile.LALTFLAG}, + {VK: KvkFile.BUILDER_KVK_SHIFT_STATE.KVKS_RALT, KMX: KMX.KMXFile.RALTFLAG} + ]; + + let result = 0; + for(let i = 0; i < Map.length; i++) { + if (ShiftState & Map[i].VK) { + result |= Map[i].KMX; + } + } + + return result; +} + + +function VKShiftToLayerName(shift: number): string { + + const masks: string[] = [ + 'leftctrl', + 'rightctrl', + 'leftalt', + 'rightalt', + 'shift', + 'ctrl', + 'alt' + ]; + + shift = VkShiftStateToKmxShiftState(shift); + if(shift == 0) { + return 'default'; + } + + let result = ''; + for(let i = 0; i < masks.length; i++) { + if(shift & (1 << i)) { + result += masks[i] + '-'; + } + } + return result.substring(0, result.length - 1); +} + + +function VisualKeyboardToKLS(FVK: VisualKeyboard.VisualKeyboard): string { + + interface TLayer { + shift: number; + name: string; + keys: string[]; + }; + + let layers: TLayer[] = []; + + // Discover the layers used in the visual keyboard + for(let key of FVK.keys) { + if(key.flags & KvkFile.BUILDER_KVK_KEY_FLAGS.kvkkUnicode) { + // Find the index of the key in KMW VK arrays + let n = CKeymanWebKeyCodes[key.vkey]; + if(n == 0xFF) { + continue; + } + + let layer = layers.find(layer => layer.shift == key.shift); + if(!layer) { + // 0-64 covers all possible VirtualKeyCodes in CKemyanWebKeyCodes + layer = { shift: key.shift, name: '', keys: new Array(65)}; + layers.push(layer); + } + layer.keys[n] = key.text; + } + } + + // Build the layer array + + let result = nl+FTabStop+'this.KV.KLS={'+nl; + + for(let i = 0; i < layers.length; i++) { + let layer = layers[i]; + result += `${FTabStop}${FTabStop}"${VKShiftToLayerName(layer.shift)}": [`; + for(let j = 0; j < layer.keys.length - 1; j++) { + result += '"'+WideQuote(layer.keys[j] ?? '')+'",'; + } + result += '"'+WideQuote(layer.keys[layer.keys.length-1] ?? '')+'"]'; + if(i < layers.length - 1) { + result += ',' + nl; + } + } + result += nl+FTabStop+'}'; + return result; +} + +function BuildBKFromKLS(debug: boolean): string { + const func = + 'function(x){var e=Array.apply(null,Array(65)).map(String.prototype.valueOf,"")'+ + ',r=[],v,i,m=[\'default\',\'shift\',\'ctrl\',\'shift-ctrl\',\'alt\',\'shift-alt\','+ + '\'ctrl-alt\',\'shift-ctrl-alt\'];for(i=m.length-1;i>=0;i--)if((v=x[m[i]])||r.length)'+ + 'r=(v?v:e).slice().concat(r);return r}'; + const func_debug = + 'function(x){'+nl+ + ' var'+nl+ + ' empty=Array.apply(null, Array(65)).map(String.prototype.valueOf,""),'+nl+ + ' result=[], v, i,'+nl+ + ' modifiers=[\'default\',\'shift\',\'ctrl\',\'shift-ctrl\',\'alt\',\'shift-alt\',\'ctrl-alt\',\'shift-ctrl-alt\'];'+nl+ + ' for(i=modifiers.length-1;i>=0;i--) {'+nl+ + ' v = x[modifiers[i]];'+nl+ + ' if(v || result.length > 0) {'+nl+ + ' result=(v ? v : empty).slice().concat(result);'+nl+ + ' }'+nl+ + ' }'+nl+ + ' return result;'+nl+ + ' }'; + + return nl+FTabStop+'this.KV.BK=('+(debug ? func_debug : func)+')(this.KV.KLS)'; +} diff --git a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts index 0175072aeb..7e89aa7cdd 100644 --- a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts +++ b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts @@ -1,10 +1,13 @@ -import { KMX, CompilerCallbacks } from "@keymanapp/common-types"; +import { KVKSParseError, VisualKeyboard } from "@keymanapp/common-types"; +import { KMX, CompilerCallbacks, KvkFileReader, KvksFileReader } from "@keymanapp/common-types"; import { ExpandSentinel, incxstr, xstrlen } from "../util/util.js"; // import { KEY, KEYBOARD, KMX.KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx.js"; import { options, nl, FTabStop, setupGlobals, IsKeyboardVersion10OrLater } from "./compiler-globals.js"; import CompilerOptions from "./compiler-options.js"; import { JavaScript_ContextMatch, JavaScript_KeyAsString, JavaScript_Name, JavaScript_OutputString, JavaScript_Rules, JavaScript_Shift, JavaScript_ShiftAsString, JavaScript_Store, zeroPadHex } from './javascript-strings.js'; import { CERR_InvalidBegin, CWARN_DontMixChiralAndNonChiralModifiers, ReportError } from "./messages.js"; +import { ValidateLayoutFile } from "./validate-layout-file.js"; +import { VisualKeyboardFromFile } from "./visual-keyboard-compiler.js"; export let FFix183_LadderLength: number = 100; // TODO: option @@ -12,7 +15,7 @@ function requote(s: string): string { return "'" + s.replaceAll(/(['\\])/, "\\$1") + "'"; } -function RequotedString(s: string, RequoteSingleQuotes: boolean = false): string { +export function RequotedString(s: string, RequoteSingleQuotes: boolean = false): string { // TODO: use a JSON encode let i: number = 0; while(i < s.length) { @@ -35,12 +38,12 @@ function RequotedString(s: string, RequoteSingleQuotes: boolean = false): string return s; } -export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, name: string, keyboard: KMX.KEYBOARD, FDebug: boolean = false): string { +export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: string, kmxfile: string, name: string, keyboard: KMX.KEYBOARD, FDebug: boolean = false): string { let opts: CompilerOptions = { addCompilerVersion: false, debug: FDebug }; - setupGlobals(callbacks, opts, FDebug?' ':'', FDebug?'\n':'', keyboard); + setupGlobals(callbacks, opts, FDebug?' ':'', FDebug?'\r\n':'', keyboard); // let fgp: GROUP; @@ -172,26 +175,17 @@ export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, name: string } if (sLayoutFile != '') { // I3483 - // TODO: Load sLayoutFile from file - /*try - with TStringList.Create do - try - LoadFromFile(ExtractFilePath(FInFile) + sLayoutFile, TEncoding.UTF8); - sLayoutFile := Text; - if not ValidateLayoutFile(sLayoutFile, sVKDictionary) then // I4060 - begin - sLayoutFile := ''; - end; - finally - Free; - end; - except - on E:EFOpenError do // I3683 - begin - ReportError(0, CWARN_TouchLayoutFileMissing, E.Message); // I4061 - sLayoutFile := ''; - end; - end;*/ + let path = callbacks.resolveFilename(kmnfile, sLayoutFile); + + let result = ValidateLayoutFile(keyboard, options.debug, path, sVKDictionary); + if(!result.result) { + sLayoutFile = ''; + // TODO: error + // ReportError(0, CWARN_TouchLayoutFileInvalid, 'Touch layout file is not valid'); + } else { + // TODO: reusing the same variable here is ugly + sLayoutFile = result.output; + } } // Default to hide underlying layout characters. This is overridden by touch @@ -200,22 +194,34 @@ export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, name: string let fDisplayUnderlying = false; if (sVisualKeyboard != '') { - //TODO: Load sVisualKeyboard from file - /* - try - // The Keyman .kmx compiler will change the value of this store from a - // .kvks to a .kvk during the build. Earlier in the build, the visual keyboard - // would have been compiled, so we need to account for that and use that file. + // TODO: stop reusing sVisualKeyboard for both filename and content + let path = callbacks.resolveFilename(kmnfile, sVisualKeyboard); - sVisualKeyboard := VisualKeyboardFromFile(ExtractFilePath(FOutFile) + sVisualKeyboard, fDisplayUnderlying); - except - on E:EFOpenError do // I3947 - begin - ReportError(0, CWARN_VisualKeyboardFileMissing, E.Message); // I4061 - sVisualKeyboard := 'null'; - end; - end; - */ + let kvk: VisualKeyboard.VisualKeyboard; + if(path.match(/\.kvks$/i)) { + let reader = new KvksFileReader(); + let source = reader.read(callbacks.loadFile(path)); + reader.validate(source, callbacks.loadSchema("kvks")); // TODO: handle exceptions + let errors: KVKSParseError[]; + kvk = reader.transform(source, errors); + // TODO: log errors + } + else { + // Note: very old keyboard sources may still have .kvk as an xml + // file, but we'll treat that as an error rather than silently + // falling back to KvksFileReader + let reader = new KvkFileReader(); + kvk = reader.read(callbacks.loadFile(path)); + } + + let result = VisualKeyboardFromFile(kvk, options.debug); + if(!result.result) { + // TODO: error + sVisualKeyboard = 'null'; + } + else { + sVisualKeyboard = result.result; + } } else { sVisualKeyboard = 'null'; @@ -236,7 +242,7 @@ export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, name: string // Following line caches the Keyman major version `${FTabStop}this._v=(typeof keyman!="undefined"&&typeof keyman.version=="string")?parseInt(keyman.version,10):9;${nl}` + `${FTabStop}this.KI="${sName}";${nl}` + - `${FTabStop}this.KN="${RequotedString(sFullName)}";${nl}`, nl, + `${FTabStop}this.KN="${RequotedString(sFullName)}";${nl}` + `${FTabStop}this.KMINVER="${(keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MAJOR) >> 8}.${keyboard.fileVersion & KMX.KMXFile.VERSION_MASK_MINOR}";${nl}` + `${FTabStop}this.KV=${sVisualKeyboard};${nl}` + `${FTabStop}this.KDU=${fDisplayUnderlying?'1':'0'};${nl}` + diff --git a/developer/src/kmc-kmw/test/test-compiler-manual.ts b/developer/src/kmc-kmw/test/test-compiler-manual.ts index af2589b833..9f4f5ea4db 100644 --- a/developer/src/kmc-kmw/test/test-compiler-manual.ts +++ b/developer/src/kmc-kmw/test/test-compiler-manual.ts @@ -5,6 +5,7 @@ import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; import { Compiler } from '@keymanapp/kmc-kmn'; import { KMX, KmxFileReader } from '@keymanapp/common-types'; import { WriteCompiledKeyboard } from '../src/compiler/write-compiled-keyboard.js'; +import { extractTouchLayout } from './util.js'; const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/'); const fixturesDir = __dirname + '/../../test/fixtures/'; @@ -28,7 +29,8 @@ if(!await kmxCompiler.init()) { // TODO: runToMemory, add option to kmxCompiler to store debug-data for conversion to .js (e.g. store metadata, group readonly metadata, etc) if(!kmxCompiler.run(infile, outfile, callbacks, { shouldAddCompilerVersion: false, - saveDebug: true + saveDebug: true, + target: 'js' })) { callbacks.printMessages(); process.exit(1); @@ -37,12 +39,16 @@ if(!kmxCompiler.run(infile, outfile, callbacks, { const reader = new KmxFileReader(); const keyboard: KMX.KEYBOARD = reader.read(callbacks.loadFile(outfile)); -const js = WriteCompiledKeyboard(callbacks, 'khmer_angkor', keyboard, true); +const js = WriteCompiledKeyboard(callbacks, infile, outfile, 'khmer_angkor', keyboard, true); callbacks.printMessages(); const fjs = fs.readFileSync(fixtureName, 'utf8'); -if(fjs !== js) { + +const expected = extractTouchLayout(fjs); +const actual = extractTouchLayout(js); + +if(expected.js !== actual.js) { fs.writeFileSync(testOutfile, js); console.error('JS not equal'); process.exit(1); diff --git a/developer/src/kmc-kmw/test/test-compiler.ts b/developer/src/kmc-kmw/test/test-compiler.ts index 7fb0efd9ce..7332d71bda 100644 --- a/developer/src/kmc-kmw/test/test-compiler.ts +++ b/developer/src/kmc-kmw/test/test-compiler.ts @@ -8,6 +8,7 @@ import fs from 'fs'; import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; import { Compiler } from '@keymanapp/kmc-kmn'; import { KMX, KmxFileReader } from '@keymanapp/common-types'; +import { extractTouchLayout } from './util.js'; const __dirname = dirname(fileURLToPath(import.meta.url)).replace(/\\/g, '/'); const fixturesDir = __dirname + '/../../test/fixtures/'; @@ -37,19 +38,28 @@ describe('Compiler class', function() { const kmxCompiler = new Compiler(); assert.isTrue(await kmxCompiler.init()); - // TODO: runToMemory, add option to kmxCompiler to store debug-data for conversion to .js (e.g. store metadata, group readonly metadata, etc) - assert.isTrue(kmxCompiler.run(infile, outfile, callbacks)); + // TODO: runToMemory, add option to kmxCompiler to store debug-data for conversion to .js (e.g. store metadata, group readonly metadata, visual keyboard source filename, etc) + assert.isTrue(kmxCompiler.run(infile, outfile, callbacks, { + shouldAddCompilerVersion: false, + saveDebug: true, + target: 'js' + })); const reader = new KmxFileReader(); const keyboard: KMX.KEYBOARD = reader.read(callbacks.loadFile(outfile)); - const js = WriteCompiledKeyboard(callbacks, 'khmer_angkor', keyboard, true); - // const js = compiler.compile('khmer_angkor', keyboard); + const js = WriteCompiledKeyboard(callbacks, infile, outfile, 'khmer_angkor', keyboard, true); const fjs = fs.readFileSync(fixtureName, 'utf8'); - if(fjs !== js) { - fs.writeFileSync(testOutfile, js); - assert.fail('JS not equal'); - } + + const expected = extractTouchLayout(fjs); + const actual = extractTouchLayout(js); + + fs.writeFileSync(testOutfile + '.strip.js', actual.js); + fs.writeFileSync(fixtureName + '.strip.js', expected.js); + fs.writeFileSync(testOutfile, js); + + assert.deepEqual(actual.js, expected.js); + assert.deepEqual(JSON.parse(actual.touchLayout), JSON.parse(expected.touchLayout)); }); }); \ No newline at end of file diff --git a/developer/src/kmc-kmw/test/tsconfig.json b/developer/src/kmc-kmw/test/tsconfig.json index abdb3a7cfe..3159c14bfd 100644 --- a/developer/src/kmc-kmw/test/tsconfig.json +++ b/developer/src/kmc-kmw/test/tsconfig.json @@ -14,7 +14,8 @@ }, }, "include": [ - "**/test-*.ts" + "**/test-*.ts", + "util.ts" ], "references": [ { "path": "../../../../common/web/types/" }, diff --git a/developer/src/kmc-kmw/test/util.ts b/developer/src/kmc-kmw/test/util.ts new file mode 100644 index 0000000000..f63e8dd26e --- /dev/null +++ b/developer/src/kmc-kmw/test/util.ts @@ -0,0 +1,19 @@ + +interface ETLResult { + js: string; + touchLayout: string; +} + +export function extractTouchLayout(js: string): ETLResult|null { + let m = /KVKL=(?.+?);[\r\n]/ds.exec(js); + if(!m) { + return null; + } + + let kvkl = (m).indices.groups.kvkl; + + return { + js: js.substring(0, kvkl[0]) + 'null' + js.substring(kvkl[1]), + touchLayout: m.groups?.['kvkl'] ?? '' + }; +} diff --git a/developer/src/kmc-kmw/tsconfig.json b/developer/src/kmc-kmw/tsconfig.json index fb2abd93e3..4fabe4a39d 100644 --- a/developer/src/kmc-kmw/tsconfig.json +++ b/developer/src/kmc-kmw/tsconfig.json @@ -5,21 +5,18 @@ "outDir": "build/src/", "rootDir": "src/", "baseUrl": ".", - "allowSyntheticDefaultImports": true, // for ajv - "paths": { - // "@keymanapp/keyman-version": ["../../../common/web/keyman-version/keyman-version.mts"], "@keymanapp/common-types": ["../../../common/web/types/src/main"], - // "@keymanapp/": ["core/include/ldml/ldml-keyboard-constants"], + "@keymanapp/kmc-kmn": ["../kmc-kmn/src/main"], }, }, "include": [ "src/**/*.ts" -, "src/compiler/__keymanweb-compiler.ts.tmp" ], + ], "references": [ - // { "path": "../../../common/web/keyman-version/tsconfig.esm.json" }, { "path": "../../../common/web/types/" }, + { "path": "../kmc-kmn/" }, { "path": "../../../core/include/ldml/"}, ] } diff --git a/developer/src/kmcmpdll/Compiler.cpp b/developer/src/kmcmpdll/Compiler.cpp index 89defad84d..847a1ff78c 100644 --- a/developer/src/kmcmpdll/Compiler.cpp +++ b/developer/src/kmcmpdll/Compiler.cpp @@ -334,7 +334,7 @@ extern "C" BOOL __declspec(dllexport) CompileKeyboardFileEx(PSTR pszInfile, PSTR if ( flag_use_new_kmcomp ) { - return kmcmp_CompileKeyboardFile(pszInfile, pszOutfile, ASaveDebug, ACompilerWarningsAsErrors,AWarnDeprecatedCode, kmcmpMsgproc, (void*) pMsgProc); + return kmcmp_CompileKeyboardFile(pszInfile, pszOutfile, ASaveDebug, ACompilerWarningsAsErrors,AWarnDeprecatedCode, kmcmpMsgproc, (void*) pMsgProc, Target); } //printf("---> stayed in CompileKeyboardFile() of kmcmpdll\n"); diff --git a/developer/src/kmcmplib/include/kmcmplibapi.h b/developer/src/kmcmplib/include/kmcmplibapi.h index 97d46c3c36..8360dd8ea4 100644 --- a/developer/src/kmcmplib/include/kmcmplibapi.h +++ b/developer/src/kmcmplib/include/kmcmplibapi.h @@ -32,7 +32,8 @@ EXTERN bool kmcmp_CompileKeyboardFile( bool ACompilerWarningsAsErrors, bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, - void* AmsgprocContext + void* AmsgprocContext, + int target // CKF_KEYMAN || CKF_KEYMANWEB ); /* Compile target */ diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index 06e707e7ea..48d97120d5 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -1042,12 +1042,21 @@ KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE pp2[4] = 0; } - delete[] sp->dpString; - sp->dpString = q; + if(CompileTarget == CKF_KEYMAN) { + // When we compile to kmx, we want to save this info into + // the .kmx, but for KMW, we need the original source file + // for the KMW compiler process + delete[] sp->dpString; + sp->dpString = q; + } - if ((msg = CheckFilenameConsistency( (sp->dpString), FALSE)) != CERR_None) { + if ((msg = CheckFilenameConsistency(q, FALSE)) != CERR_None) { return msg; } + + if(CompileTarget == CKF_KEYMANWEB) { + delete[] q; + } } break; case TSS_KMW_RTL: diff --git a/developer/src/kmcmplib/src/CompilerInterfaces.cpp b/developer/src/kmcmplib/src/CompilerInterfaces.cpp index 89c4655d16..f684da6e58 100644 --- a/developer/src/kmcmplib/src/CompilerInterfaces.cpp +++ b/developer/src/kmcmplib/src/CompilerInterfaces.cpp @@ -53,7 +53,7 @@ EXTERN bool kmcmp_Wasm_SetCompilerOptions(int ShouldAddCompilerVersion) { EXTERN bool kmcmp_Wasm_CompileKeyboardFile(char* pszInfile, char* pszOutfile, int ASaveDebug, int ACompilerWarningsAsErrors, - int AWarnDeprecatedCode, char* msgProc + int AWarnDeprecatedCode, char* msgProc, int target ) { return kmcmp_CompileKeyboardFile( pszInfile, @@ -62,7 +62,8 @@ EXTERN bool kmcmp_Wasm_CompileKeyboardFile(char* pszInfile, ACompilerWarningsAsErrors, AWarnDeprecatedCode, wasm_CompilerMessageProc, - msgProc + msgProc, + target ); } @@ -78,7 +79,7 @@ EXTERN int kmcmp_Wasm_ParseUnicodeSet(char* pat, EXTERN bool kmcmp_CompileKeyboardFile(char* pszInfile, char* pszOutfile, bool ASaveDebug, bool ACompilerWarningsAsErrors, - bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, void* AmsgprocContext + bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, void* AmsgprocContext, int Target ) { FILE* fp_in = NULL; FILE* fp_out = NULL; @@ -90,7 +91,7 @@ EXTERN bool kmcmp_CompileKeyboardFile(char* pszInfile, kmcmp::FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865 AWarnDeprecatedCode_GLOBAL_LIB = AWarnDeprecatedCode; - kmcmp::CompileTarget = CKF_KEYMAN; + kmcmp::CompileTarget = Target; if (!pMsgproc || !pszInfile || !pszOutfile) SetError(CERR_BadCallParams); diff --git a/developer/src/kmcmplib/tests/api-test.cpp b/developer/src/kmcmplib/tests/api-test.cpp index 4c46b1f1a4..4c08272d4b 100644 --- a/developer/src/kmcmplib/tests/api-test.cpp +++ b/developer/src/kmcmplib/tests/api-test.cpp @@ -62,7 +62,7 @@ void test_kmcmp_CompileKeyboardFile() { fclose(fp); // It should fail when a zero-byte file is passed in - assert(!kmcmp_CompileKeyboardFile(kmn_file, kmx_file, true, false, true, msgproc, nullptr)); + assert(!kmcmp_CompileKeyboardFile(kmn_file, kmx_file, true, false, true, msgproc, nullptr, CKF_KEYMAN)); assert(error_vec.size() == 1); assert(error_vec[0] == CERR_CannotReadInfile); diff --git a/developer/src/kmcmplib/tests/kmcompxtest.cpp b/developer/src/kmcmplib/tests/kmcompxtest.cpp index 1ce542917d..fc1e23a514 100644 --- a/developer/src/kmcmplib/tests/kmcompxtest.cpp +++ b/developer/src/kmcmplib/tests/kmcompxtest.cpp @@ -78,7 +78,7 @@ int main(int argc, char *argv[]) return __LINE__; } - if(kmcmp_CompileKeyboardFile(kmn_file, kmx_file, true, false, true, msgproc, nullptr)) { + if(kmcmp_CompileKeyboardFile(kmn_file, kmx_file, true, false, true, msgproc, nullptr, CKF_KEYMAN)) { char* testname = strrchr( (char*) kmn_file, '/') + 1; if(strncmp(testname, pfirst5, 5) == 0){ return __LINE__; // exit code: CERR_ in Name + no Error found From d00396467a6c12dde80bb3798d2eeb5555238fe6 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Fri, 5 May 2023 10:26:34 +0700 Subject: [PATCH 07/21] chore(developer): add kmc-kmw to npm workspace --- developer/src/kmc-kmw/package-lock.json | 1789 ----------------------- package.json | 1 + tsconfig.esm.json | 4 + 3 files changed, 5 insertions(+), 1789 deletions(-) delete mode 100644 developer/src/kmc-kmw/package-lock.json diff --git a/developer/src/kmc-kmw/package-lock.json b/developer/src/kmc-kmw/package-lock.json deleted file mode 100644 index 1a8b017d98..0000000000 --- a/developer/src/kmc-kmw/package-lock.json +++ /dev/null @@ -1,1789 +0,0 @@ -{ - "name": "@keymanapp/kmc-kmw", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@keymanapp/kmc-kmw", - "license": "MIT", - "dependencies": { - "@keymanapp/keyman-version": "*", - "ajv": "^8.11.0", - "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", - "semver": "^7.3.7", - "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" - }, - "devDependencies": { - "@types/chai": "^4.1.7", - "@types/mocha": "^5.2.7", - "@types/node": "^10.14.6", - "@types/semver": "^7.3.12", - "@types/xml2js": "^0.4.5", - "c8": "^7.12.0", - "chai": "^4.3.4", - "chalk": "^2.4.2", - "mocha": "^8.4.0", - "ts-node": "^9.1.1", - "typescript": "^4.9.5" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.18", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", - "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "3.1.0", - "@jridgewell/sourcemap-codec": "1.4.14" - } - }, - "node_modules/@keymanapp/keyman-version": { - "version": "16.0.139", - "resolved": "https://registry.npmjs.org/@keymanapp/keyman-version/-/keyman-version-16.0.139.tgz", - "integrity": "sha512-hUCgWq+msSTSxra9xOhSxN/nCPxk/hLnPHHTUnFvIc39uxJ/DjNQGkxtsxTdxjCqWZr7frE/2kT7ob9h5Dh5eQ==" - }, - "node_modules/@types/chai": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", - "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", - "dev": true - }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", - "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", - "dev": true - }, - "node_modules/@types/mocha": { - "version": "5.2.7", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "10.17.60", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", - "dev": true - }, - "node_modules/@types/xml2js": { - "version": "0.4.11", - "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.11.tgz", - "integrity": "sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@ungap/promise-all-settled": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", - "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==", - "dev": true - }, - "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/c8": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.13.0.tgz", - "integrity": "sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA==", - "dev": true, - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@istanbuljs/schema": "^0.1.3", - "find-up": "^5.0.0", - "foreground-child": "^2.0.0", - "istanbul-lib-coverage": "^3.2.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-reports": "^3.1.4", - "rimraf": "^3.0.2", - "test-exclude": "^6.0.0", - "v8-to-istanbul": "^9.0.0", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9" - }, - "bin": { - "c8": "bin/c8.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chai": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", - "dev": true, - "dependencies": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^4.1.2", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/chokidar": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz", - "integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.5.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.1" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/convert-source-map": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", - "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", - "dev": true - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "dependencies": { - "type-detect": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } - }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", - "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.5.tgz", - "integrity": "sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==", - "dev": true, - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-symbols": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", - "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", - "dev": true, - "dependencies": { - "chalk": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", - "dev": true, - "dependencies": { - "get-func-name": "^2.0.0" - } - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha": { - "version": "8.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@ungap/promise-all-settled": "1.1.2", - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.1", - "debug": "4.3.1", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.1.6", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "4.0.0", - "log-symbols": "4.0.0", - "minimatch": "3.0.4", - "ms": "2.1.3", - "nanoid": "3.1.20", - "serialize-javascript": "5.0.1", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "which": "2.0.2", - "wide-align": "1.1.3", - "workerpool": "6.1.0", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 10.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.1.20", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz", - "integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readdirp": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz", - "integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/restructure": { - "version": "3.0.0", - "resolved": "git+ssh://git@github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", - "integrity": "sha512-2vBFOLc0+dkUb3Pnpl87o+B4SIc3MAm3P8PXT8YFkP51URFGsgTgm3gAnwTX2jXSEd/5eT9n7C733loG6OaVgw==", - "license": "MIT" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/semver": { - "version": "7.3.7", - "license": "ISC", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-javascript": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", - "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-node": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", - "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", - "dev": true, - "dependencies": { - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "typescript": ">=2.7" - } - }, - "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/v8-to-istanbul": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", - "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", - "dev": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/workerpool": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.1.0.tgz", - "integrity": "sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/xml2js": { - "version": "0.4.23", - "resolved": "git+ssh://git@github.com/keymanapp/dependency-node-xml2js.git#535fe732dc408d697e0f847c944cc45f0baf0829", - "integrity": "sha512-5CS+yWxp0qg8zO7ng/iXrBZm2FXgpiJ+RJ3E0LzRxDXChESqzazRwzl8sXYe8/7je/NfwG4EXcClaRKUkcIvtQ==", - "license": "MIT", - "dependencies": { - "sax": ">=0.6.0", - "xmlbuilder": "~11.0.0" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/package.json b/package.json index 7a2b53d50d..9b62b5a341 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "core/include/ldml", "developer/src/common/web/test-helpers", "developer/src/kmc-kmn", + "developer/src/kmc-kmw", "developer/src/kmc-ldml", "developer/src/kmc-model", "developer/src/kmc-model-info", diff --git a/tsconfig.esm.json b/tsconfig.esm.json index 44bf4011df..63001931f1 100644 --- a/tsconfig.esm.json +++ b/tsconfig.esm.json @@ -8,10 +8,14 @@ { "path": "./core/include/ldml/tsconfig.json" }, //{ "path": "./developer/src/kmc/test/tsconfig.json" }, + { "path": "./developer/src/common/web/test-helpers/tsconfig.json" }, + { "path": "./developer/src/kmc/tsconfig.json" }, { "path": "./developer/src/kmc-kmn/test/tsconfig.json" }, { "path": "./developer/src/kmc-kmn/tsconfig.json" }, + { "path": "./developer/src/kmc-kmw/test/tsconfig.json" }, + { "path": "./developer/src/kmc-kmw/tsconfig.json" }, { "path": "./developer/src/kmc-ldml/test/tsconfig.json" }, { "path": "./developer/src/kmc-ldml/tsconfig.json" }, { "path": "./developer/src/kmc-model/test/tsconfig.json" }, From c4b8f574cfc16c83efb437fb8113686879922862 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 9 May 2023 10:00:51 +0700 Subject: [PATCH 08/21] chore(developer): add kmc-kmw to kmc deps --- developer/src/kmc/build.sh | 2 ++ developer/src/kmc/package.json | 1 + developer/src/kmc/tsconfig.json | 2 ++ 3 files changed, 5 insertions(+) diff --git a/developer/src/kmc/build.sh b/developer/src/kmc/build.sh index 61ccd3bdca..6b62da5ae9 100755 --- a/developer/src/kmc/build.sh +++ b/developer/src/kmc/build.sh @@ -21,6 +21,7 @@ builder_describe "Build Keyman Keyboard Compiler kmc" \ "@/common/web/keyman-version" \ "@/common/web/types" \ "@/developer/src/kmc-kmn" \ + "@/developer/src/kmc-kmw" \ "@/developer/src/kmc-ldml" \ "@/developer/src/kmc-model" \ "@/developer/src/kmc-model-info" \ @@ -113,6 +114,7 @@ readonly PACKAGES=( common/models/types core/include/ldml developer/src/kmc-kmn + developer/src/kmc-kmw developer/src/kmc-ldml developer/src/kmc-model developer/src/kmc-model-info diff --git a/developer/src/kmc/package.json b/developer/src/kmc/package.json index 695ebc96e3..0c9c2cece2 100644 --- a/developer/src/kmc/package.json +++ b/developer/src/kmc/package.json @@ -40,6 +40,7 @@ "@keymanapp/keyman-version": "*", "@keymanapp/common-types": "*", "@keymanapp/kmc-kmn": "*", + "@keymanapp/kmc-kmw": "*", "@keymanapp/kmc-ldml": "*", "@keymanapp/kmc-model": "*", "@keymanapp/kmc-model-info": "*", diff --git a/developer/src/kmc/tsconfig.json b/developer/src/kmc/tsconfig.json index 9b6eb601ac..777d73e648 100644 --- a/developer/src/kmc/tsconfig.json +++ b/developer/src/kmc/tsconfig.json @@ -8,6 +8,7 @@ "paths": { "@keymanapp/common-types": [ "../../../common/web/types/src/main" ], "@keymanapp/kmc-kmn": [ "../kmc-kmn/src/main" ], + "@keymanapp/kmc-kmw": [ "../kmc-kmw/src/main" ], "@keymanapp/kmc-ldml": [ "../kmc-ldml/src/main" ], "@keymanapp/kmc-model": [ "../kmc-model/src/main" ], "@keymanapp/kmc-model-info": [ "../kmc-model-info/src/model-info-compiler" ], @@ -21,6 +22,7 @@ { "path": "../../../common/web/keyman-version/tsconfig.esm.json" }, { "path": "../../../common/web/types" }, { "path": "../kmc-kmn" }, + { "path": "../kmc-kmw" }, { "path": "../kmc-ldml" }, { "path": "../kmc-model" }, { "path": "../kmc-model-info" }, From ea374aaffd2e6adcc57c7ba8cf47d854c31b3c58 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 9 May 2023 12:03:21 +0700 Subject: [PATCH 09/21] chore(developer): rollback temp kmcomp js build stub --- .../src/tike/compile/CompileKeymanWeb.pas | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/developer/src/tike/compile/CompileKeymanWeb.pas b/developer/src/tike/compile/CompileKeymanWeb.pas index e55966e5c3..13d5219f70 100644 --- a/developer/src/tike/compile/CompileKeymanWeb.pas +++ b/developer/src/tike/compile/CompileKeymanWeb.pas @@ -275,7 +275,6 @@ uses System.TypInfo, CompileErrorCodes, - TempFileManager, JsonUtil, KeymanDeveloperOptions, Keyman.System.KeyboardUtils, @@ -283,7 +282,6 @@ uses kmxfileutils, TouchLayout, Unicode, - utilexecute, utilstr, VisualKeyboard, VKeys; @@ -305,7 +303,6 @@ function TCompileKeymanWeb.Compile(AOwnerProject: TProject; const InFile: string var WarnDeprecatedCode: Boolean; Data: string; - TempOutFile: TTempFile; begin FUnreachableKeys.Clear; @@ -340,40 +337,9 @@ begin WarnDeprecatedCode := True; end; - TempOutFile := TTempFileManager.Get('.kmx'); - GCallbackW := Callback; FCallFunctions := TStringList.Create; try - if CompileKeyboardFileEx(PChar(InFile), PChar(TempOutFile.Name), False, FCompilerWarningsAsErrors, - WarnDeprecatedCode, WebCompilerMessageA, CKF_KEYMANWEB) > 0 then - begin - if Assigned(AOwnerProject) and - Assigned(AOwnerProject.CompilerMessageFile) and - AOwnerProject.CompilerMessageFile.HasCompileWarning and - FCompilerWarningsAsErrors then - FError := True; - - if not FError then - begin - CopyFile(PChar(TempOutFile.Name), PChar(OutFile+'.kmx'), False); - // TODO: convert by calling node kmwc.js - // TODO: add -// TUtilExecute('node.exe kmwc.js "'+TempOutFile.Name+'" "'+OutFile+'"'); - {Data := WriteCompiledKeyboard; - - if not FError then - with TStringStream.Create(Data, TEncoding.UTF8) do - try - SaveToFile(OutFile); - finally - Free; - end;} - end; - - Result := not FError; // I1971 - -{ if CompileKeyboardFileToBuffer(PChar(InFile), @fk, FCompilerWarningsAsErrors, WarnDeprecatedCode, WebCompilerMessageA, CKF_KEYMANWEB) > 0 then // I3482 // I4866 // I4865 @@ -399,7 +365,6 @@ begin end; Result := not FError; // I1971 -} end else begin From eac6651c03bbd0981f05ae5ae476df5ea57cbef0 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 9 May 2023 13:09:55 +0700 Subject: [PATCH 10/21] chore(developer): use older pattern for row id In order to match existing behaviour with the legacy KeymanWeb compiler, we should use quoted numbers for row ids. This behaviour can probably be changed over to the new model in the future, but for now this prevents unit tests from causing us grief. --- developer/src/kmc-ldml/test/fixtures/basic-no-debug.js | 2 +- developer/src/kmc-ldml/test/fixtures/basic.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js b/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js index 177d55963e..48317a457a 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js +++ b/developer/src/kmc-ldml/test/fixtures/basic-no-debug.js @@ -1 +1 @@ -if(typeof keyman === 'undefined') {console.error('Keyboard requires KeymanWeb 16.0 or later');} else {KeymanWeb.KR(new Keyboard_basic());}function Keyboard_basic() {this.KI="Keyboard_basic";this.KN={"value":"TestKbd"};this.KMINVER="16.0";this.KV={F: '10pt "Arial"', K102: 0};this.KV.KLS={TODO_LDML: 2};this.KDU=1;this.KH="";this.KM=0;this.KBVER="1.0.0";this.KMBM=0;this.KVKL={"desktop":{"defaultHint":"none","layer":[{"id":"base","row":[{"id":0,"key":[{"id":"T_hmaqtugha","text":"ħ"},{"id":"T_that","text":"ថា"}]}]}]}};this.gs=function(t,e){return 0;};} \ No newline at end of file +if(typeof keyman === 'undefined') {console.error('Keyboard requires KeymanWeb 16.0 or later');} else {KeymanWeb.KR(new Keyboard_basic());}function Keyboard_basic() {this.KI="Keyboard_basic";this.KN={"value":"TestKbd"};this.KMINVER="16.0";this.KV={F: '10pt "Arial"', K102: 0};this.KV.KLS={TODO_LDML: 2};this.KDU=1;this.KH="";this.KM=0;this.KBVER="1.0.0";this.KMBM=0;this.KVKL={"desktop":{"defaultHint":"none","layer":[{"id":"base","row":[{"id":"0","key":[{"id":"T_hmaqtugha","text":"ħ"},{"id":"T_that","text":"ថា"}]}]}]}};this.gs=function(t,e){return 0;};} \ No newline at end of file diff --git a/developer/src/kmc-ldml/test/fixtures/basic.js b/developer/src/kmc-ldml/test/fixtures/basic.js index 59a1902ee6..179fa0dc06 100644 --- a/developer/src/kmc-ldml/test/fixtures/basic.js +++ b/developer/src/kmc-ldml/test/fixtures/basic.js @@ -24,7 +24,7 @@ function Keyboard_basic() { "id": "base", "row": [ { - "id": 0, + "id": "0", "key": [ { "id": "T_hmaqtugha", From 80e5d650de7ed1cb3f17b9bb1bf8a07b83d1dabe Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 9 May 2023 15:24:35 +0700 Subject: [PATCH 11/21] chore(developer): split CKF_KEYMANWEB for typescript compiler --- developer/src/common/delphi/compiler/compile.pas | 1 + developer/src/kmc-kmn/src/compiler/compiler.ts | 5 +++-- developer/src/kmcmplib/include/kmcmplibapi.h | 5 +++-- developer/src/kmcmplib/src/Compiler.cpp | 16 ++++++++-------- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/developer/src/common/delphi/compiler/compile.pas b/developer/src/common/delphi/compiler/compile.pas index 9ebea18ad2..04470239c5 100644 --- a/developer/src/common/delphi/compiler/compile.pas +++ b/developer/src/common/delphi/compiler/compile.pas @@ -141,6 +141,7 @@ type const CKF_KEYMAN = 0; CKF_KEYMANWEB = 1; + // CKF_KEYMANWEB_MODERN = 2; // used only by Typescript-based compiler const CERR_FATAL = $00008000; diff --git a/developer/src/kmc-kmn/src/compiler/compiler.ts b/developer/src/kmc-kmn/src/compiler/compiler.ts index 5ca3f9a942..18995796e2 100644 --- a/developer/src/kmc-kmn/src/compiler/compiler.ts +++ b/developer/src/kmc-kmn/src/compiler/compiler.ts @@ -148,7 +148,8 @@ export class KmnCompiler { private runCompiler(infile: string, outfile: string, options: CompilerOptions): boolean { const CKF_KEYMAN = 0; - const CKF_KEYMANWEB = 1; + // const CKF_KEYMANWEB = 1; // not used -- legacy compiler only + const CKF_KEYMANWEB_MODERN = 2; try { if (!this.wasm.setCompilerOptions(options.shouldAddCompilerVersion ? 1 : 0)) { @@ -161,7 +162,7 @@ export class KmnCompiler { options.compilerWarningsAsErrors ? 1 : 0, options.warnDeprecatedCode ? 1 : 0, this.callbackName, - options.target == 'js' ? CKF_KEYMANWEB : CKF_KEYMAN); + options.target == 'js' ? CKF_KEYMANWEB_MODERN : CKF_KEYMAN); } catch(e) { this.callbacks.reportMessage(CompilerMessages.Fatal_UnexpectedException({e:e})); return false; diff --git a/developer/src/kmcmplib/include/kmcmplibapi.h b/developer/src/kmcmplib/include/kmcmplibapi.h index 8360dd8ea4..2df44d8b6d 100644 --- a/developer/src/kmcmplib/include/kmcmplibapi.h +++ b/developer/src/kmcmplib/include/kmcmplibapi.h @@ -33,13 +33,14 @@ EXTERN bool kmcmp_CompileKeyboardFile( bool AWarnDeprecatedCode, kmcmp_CompilerMessageProc pMsgproc, void* AmsgprocContext, - int target // CKF_KEYMAN || CKF_KEYMANWEB + int target // CKF_KEYMAN || CKF_KEYMANWEB || CKF_KEYMANWEB_MODERN ); /* Compile target */ #define CKF_KEYMAN 0 -#define CKF_KEYMANWEB 1 +#define CKF_KEYMANWEB 1 // For legacy kmcomp compiler, to be deprecated and removed +#define CKF_KEYMANWEB_MODERN 2 // For Typescript kmc-kmw compiler EXTERN bool kmcmp_CompileKeyboardFileToBuffer( char* pszInfile, diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index 48d97120d5..4292dd21d9 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -1042,10 +1042,10 @@ KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE pp2[4] = 0; } - if(CompileTarget == CKF_KEYMAN) { - // When we compile to kmx, we want to save this info into - // the .kmx, but for KMW, we need the original source file - // for the KMW compiler process + if(CompileTarget != CKF_KEYMANWEB_MODERN) { + // When we compile to kmx, we want to save this info into the .kmx, and + // for the legacy kmw compiler, but for kmc-kmw, we need the original + // source file for the kmc-kmw compiler process delete[] sp->dpString; sp->dpString = q; } @@ -1054,7 +1054,7 @@ KMX_DWORD ProcessSystemStore(PFILE_KEYBOARD fk, KMX_DWORD SystemID, PFILE_STORE return msg; } - if(CompileTarget == CKF_KEYMANWEB) { + if(CompileTarget == CKF_KEYMANWEB_MODERN) { delete[] q; } } @@ -1234,7 +1234,7 @@ KMX_DWORD CheckStatementOffsets(PFILE_KEYBOARD fk, PFILE_GROUP gp, PKMX_WCHAR co // Due to a limitation in earlier versions of KeymanWeb, the minimum version // for context() referring to notany() is 14.0. See #917 for details. - if (kmcmp::CompileTarget == CKF_KEYMANWEB) { + if (kmcmp::CompileTarget != CKF_KEYMAN) { for (q = context, i = 1; *q && i < contextOffset; q = incxstr(q), i++); if (*q == UC_SENTINEL && *(q + 1) == CODE_NOTANY) { VERIFY_KEYBOARD_VERSION(fk, VERSION_140, CERR_140FeatureOnlyContextAndNotAnyWeb); @@ -1687,7 +1687,7 @@ int LineTokenType(PKMX_WCHAR *str) /* Test KeymanWeb, Keyman and KeymanOnly prefixes */ if (kmcmp::CompileTarget == CKF_KEYMAN && lpt == lptKeymanWebOnly) return T_BLANK; - if (kmcmp::CompileTarget == CKF_KEYMANWEB && lpt == lptKeymanOnly) return T_BLANK; + if (kmcmp::CompileTarget != CKF_KEYMAN && lpt == lptKeymanOnly) return T_BLANK; while (iswspace(*p)) p++; @@ -2168,7 +2168,7 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX // in the web target platform, even if there are platform() rules excluding this possibility. In that (rare) situation, the keyboard developer should simply specify // the &version to be 9.0 or whatever to avoid this behaviour. if (sFlag & (LCTRLFLAG | LALTFLAG | RCTRLFLAG | RALTFLAG | CAPITALFLAG | NOTCAPITALFLAG | NUMLOCKFLAG | NOTNUMLOCKFLAG | SCROLLFLAG | NOTSCROLLFLAG) && - kmcmp::CompileTarget == CKF_KEYMANWEB && + kmcmp::CompileTarget != CKF_KEYMAN && fk->dwFlags & KF_AUTOMATICVERSION) { VERIFY_KEYBOARD_VERSION(fk, VERSION_100, 0); } From 4416957d2ef8050e2c3fa360befaf8512f5f0283 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 9 May 2023 15:30:27 +0700 Subject: [PATCH 12/21] chore(developer): skip c8 test for kmc-kmw for now --- developer/src/kmc-kmw/build.sh | 1 + developer/src/kmc-kmw/package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/developer/src/kmc-kmw/build.sh b/developer/src/kmc-kmw/build.sh index be180cc725..aa712d10ce 100755 --- a/developer/src/kmc-kmw/build.sh +++ b/developer/src/kmc-kmw/build.sh @@ -61,6 +61,7 @@ fi #------------------------------------------------------------------------------------------------------------------- if builder_start_action test; then + # TODO: add c8 for coverage npm test builder_finish_action success test fi diff --git a/developer/src/kmc-kmw/package.json b/developer/src/kmc-kmw/package.json index fc4448b87e..c1494fb139 100644 --- a/developer/src/kmc-kmw/package.json +++ b/developer/src/kmc-kmw/package.json @@ -14,7 +14,7 @@ "scripts": { "build": "tsc -b", "tsc": "tsc", - "test": "cd test && tsc -b && cd .. && c8 mocha", + "test": "cd test && tsc -b && cd .. && mocha", "prepublishOnly": "npm run build" }, "author": "Marc Durdin (https://github.com/mcdurdin)", From 9a4f8de5e2f0cb645a75b4f47a9e02781009b723 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 11 May 2023 12:52:02 +0700 Subject: [PATCH 13/21] chore(common): npm install --- package-lock.json | 259 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) diff --git a/package-lock.json b/package-lock.json index 20d7ce98c4..5b63a9341f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1284,6 +1284,261 @@ "node": ">=0.3.1" } }, + "developer/src/kmc-ldml": { + "license": "MIT", + "dependencies": { + "@keymanapp/keyman-version": "*", + "@keymanapp/ldml-keyboard-constants": "*", + "ajv": "^8.11.0", + "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", + "semver": "^7.3.7", + "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" + }, + "devDependencies": { + "@keymanapp/developer-test-helpers": "*", + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.7", + "@types/node": "^10.14.6", + "@types/semver": "^7.3.12", + "@types/xml2js": "^0.4.5", + "c8": "^7.12.0", + "chai": "^4.3.4", + "chalk": "^2.4.2", + "mocha": "^8.4.0", + "ts-node": "^9.1.1", + "typescript": "^4.9.5" + } + }, + "developer/src/kmc-ldml/node_modules/@types/mocha": { + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", + "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", + "dev": true + }, + "developer/src/kmc-ldml/node_modules/@types/node": { + "version": "10.17.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", + "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", + "dev": true + }, + "developer/src/kmc-ldml/node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "developer/src/kmc-ldml/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "developer/src/kmc-ldml/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "developer/src/kmc-ldml/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "developer/src/kmc-ldml/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "developer/src/kmc-ldml/node_modules/js-yaml": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", + "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "developer/src/kmc-ldml/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "developer/src/kmc-ldml/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "developer/src/kmc-ldml/node_modules/mocha": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", + "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", + "dev": true, + "dependencies": { + "@ungap/promise-all-settled": "1.1.2", + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.1", + "debug": "4.3.1", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.1.6", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "4.0.0", + "log-symbols": "4.0.0", + "minimatch": "3.0.4", + "ms": "2.1.3", + "nanoid": "3.1.20", + "serialize-javascript": "5.0.1", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "which": "2.0.2", + "wide-align": "1.1.3", + "workerpool": "6.1.0", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 10.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "developer/src/kmc-ldml/node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "developer/src/kmc-ldml/node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "developer/src/kmc-ldml/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "developer/src/kmc-ldml/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "developer/src/kmc-ldml/node_modules/supports-color/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "developer/src/kmc-ldml/node_modules/ts-node": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", + "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", + "dev": true, + "dependencies": { + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "typescript": ">=2.7" + } + }, + "developer/src/kmc-ldml/node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, "developer/src/kmc-model": { "name": "@keymanapp/kmc-model", "license": "MIT", @@ -2325,6 +2580,10 @@ "resolved": "developer/src/kmc-ldml", "link": true }, + "node_modules/@keymanapp/kmc-ldml": { + "resolved": "developer/src/kmc-ldml", + "link": true + }, "node_modules/@keymanapp/kmc-model": { "resolved": "developer/src/kmc-model", "link": true From 6094457f18dd27c424be8af3bab8f9e1a3a68cf6 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Sun, 14 May 2023 12:49:44 +0700 Subject: [PATCH 14/21] chore: package-lock.json again --- package-lock.json | 50 ++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5b63a9341f..568c70e2b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "core/include/ldml", "developer/src/common/web/test-helpers", "developer/src/kmc-kmn", + "developer/src/kmc-kmw", "developer/src/kmc-ldml", "developer/src/kmc-model", "developer/src/kmc-model-info", @@ -635,6 +636,7 @@ "@keymanapp/common-types": "*", "@keymanapp/keyman-version": "*", "@keymanapp/kmc-kmn": "*", + "@keymanapp/kmc-kmw": "*", "@keymanapp/kmc-ldml": "*", "@keymanapp/kmc-model": "*", "@keymanapp/kmc-model-info": "*", @@ -1029,18 +1031,17 @@ "node": ">=0.3.1" } }, - "developer/src/kmc-ldml": { + "developer/src/kmc-kmw": { "license": "MIT", "dependencies": { - "@keymanapp/keyman-version": "*", - "@keymanapp/ldml-keyboard-constants": "*", + "@keymanapp/common-types": "*", + "@keymanapp/kmc-kmn": "*", "ajv": "^8.11.0", "restructure": "git+https://github.com/keymanapp/dependency-restructure.git#49d129cf0916d082a7278bb09296fb89cecfcc50", "semver": "^7.3.7", "xml2js": "git+https://github.com/keymanapp/dependency-node-xml2js#535fe732dc408d697e0f847c944cc45f0baf0829" }, "devDependencies": { - "@keymanapp/developer-test-helpers": "*", "@types/chai": "^4.1.7", "@types/mocha": "^5.2.7", "@types/node": "^10.14.6", @@ -1054,19 +1055,19 @@ "typescript": "^4.9.5" } }, - "developer/src/kmc-ldml/node_modules/@types/mocha": { + "developer/src/kmc-kmw/node_modules/@types/mocha": { "version": "5.2.7", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz", "integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==", "dev": true }, - "developer/src/kmc-ldml/node_modules/@types/node": { + "developer/src/kmc-kmw/node_modules/@types/node": { "version": "10.17.60", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", "dev": true }, - "developer/src/kmc-ldml/node_modules/ajv": { + "developer/src/kmc-kmw/node_modules/ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", @@ -1081,7 +1082,7 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "developer/src/kmc-ldml/node_modules/ansi-styles": { + "developer/src/kmc-kmw/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", @@ -1093,7 +1094,7 @@ "node": ">=4" } }, - "developer/src/kmc-ldml/node_modules/chalk": { + "developer/src/kmc-kmw/node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", @@ -1107,7 +1108,7 @@ "node": ">=4" } }, - "developer/src/kmc-ldml/node_modules/color-convert": { + "developer/src/kmc-kmw/node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", @@ -1116,13 +1117,13 @@ "color-name": "1.1.3" } }, - "developer/src/kmc-ldml/node_modules/color-name": { + "developer/src/kmc-kmw/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, - "developer/src/kmc-ldml/node_modules/js-yaml": { + "developer/src/kmc-kmw/node_modules/js-yaml": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", @@ -1134,12 +1135,12 @@ "js-yaml": "bin/js-yaml.js" } }, - "developer/src/kmc-ldml/node_modules/json-schema-traverse": { + "developer/src/kmc-kmw/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, - "developer/src/kmc-ldml/node_modules/minimatch": { + "developer/src/kmc-kmw/node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", @@ -1151,7 +1152,7 @@ "node": "*" } }, - "developer/src/kmc-ldml/node_modules/mocha": { + "developer/src/kmc-kmw/node_modules/mocha": { "version": "8.4.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.4.0.tgz", "integrity": "sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ==", @@ -1195,7 +1196,7 @@ "url": "https://opencollective.com/mochajs" } }, - "developer/src/kmc-ldml/node_modules/mocha/node_modules/escape-string-regexp": { + "developer/src/kmc-kmw/node_modules/mocha/node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", @@ -1207,7 +1208,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "developer/src/kmc-ldml/node_modules/mocha/node_modules/supports-color": { + "developer/src/kmc-kmw/node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", @@ -1222,13 +1223,13 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "developer/src/kmc-ldml/node_modules/ms": { + "developer/src/kmc-kmw/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "developer/src/kmc-ldml/node_modules/supports-color": { + "developer/src/kmc-kmw/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", @@ -1240,7 +1241,7 @@ "node": ">=4" } }, - "developer/src/kmc-ldml/node_modules/supports-color/node_modules/has-flag": { + "developer/src/kmc-kmw/node_modules/supports-color/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", @@ -1249,7 +1250,7 @@ "node": ">=4" } }, - "developer/src/kmc-ldml/node_modules/ts-node": { + "developer/src/kmc-kmw/node_modules/ts-node": { "version": "9.1.1", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz", "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==", @@ -1275,7 +1276,7 @@ "typescript": ">=2.7" } }, - "developer/src/kmc-ldml/node_modules/ts-node/node_modules/diff": { + "developer/src/kmc-kmw/node_modules/ts-node/node_modules/diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", @@ -1285,6 +1286,7 @@ } }, "developer/src/kmc-ldml": { + "name": "@keymanapp/kmc-ldml", "license": "MIT", "dependencies": { "@keymanapp/keyman-version": "*", @@ -2576,8 +2578,8 @@ "resolved": "developer/src/kmc-kmn", "link": true }, - "node_modules/@keymanapp/kmc-ldml": { - "resolved": "developer/src/kmc-ldml", + "node_modules/@keymanapp/kmc-kmw": { + "resolved": "developer/src/kmc-kmw", "link": true }, "node_modules/@keymanapp/kmc-ldml": { From 9978cb2d502073dfa6b146f223588c7051e791ed Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Sun, 14 May 2023 13:40:11 +0700 Subject: [PATCH 15/21] chore(developer): fix typo --- developer/src/kmc-kmn/src/compiler/compiler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/developer/src/kmc-kmn/src/compiler/compiler.ts b/developer/src/kmc-kmn/src/compiler/compiler.ts index 18995796e2..73aad247d1 100644 --- a/developer/src/kmc-kmn/src/compiler/compiler.ts +++ b/developer/src/kmc-kmn/src/compiler/compiler.ts @@ -108,6 +108,7 @@ export class KmnCompiler { this.callbacks.reportMessage(CompilerMessages.Fatal_MissingWasmModule({e})); return false; } + } return this.verifyInitialized(); } From 9d85712039d8ddb5300a61a2ed6d200ee1a37d12 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 5 Jun 2023 16:10:57 +0700 Subject: [PATCH 16/21] chore(developer): rollback unneeded kmcomp changes --- common/windows/cpp/include/legacy_kmx_file.h | 3 +- .../src/common/delphi/compiler/compile.pas | 29 +------------------ developer/src/kmcmpdll/Compiler.cpp | 7 +---- developer/src/kmcomp/kmcomp.dproj | 2 +- 4 files changed, 4 insertions(+), 37 deletions(-) diff --git a/common/windows/cpp/include/legacy_kmx_file.h b/common/windows/cpp/include/legacy_kmx_file.h index dbc81328c8..d961250912 100644 --- a/common/windows/cpp/include/legacy_kmx_file.h +++ b/common/windows/cpp/include/legacy_kmx_file.h @@ -415,8 +415,7 @@ typedef COMPILER_OPTIONS *PCOMPILER_OPTIONS; typedef int (CALLBACK *CompilerMessageProc)(int line, DWORD dwMsgCode, LPSTR szText); -extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL FSaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc); // I4865 // I4866 -extern "C" BOOL __declspec(dllexport) CompileKeyboardFileEx(PSTR pszInfile, PSTR pszOutfile, BOOL ASaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc, int Target); +//extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL FSaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc); // I4865 // I4866 #endif // _COMPILER_H diff --git a/developer/src/common/delphi/compiler/compile.pas b/developer/src/common/delphi/compiler/compile.pas index aeaf3cf8df..0124150ef6 100644 --- a/developer/src/common/delphi/compiler/compile.pas +++ b/developer/src/common/delphi/compiler/compile.pas @@ -143,7 +143,6 @@ type const CKF_KEYMAN = 0; CKF_KEYMANWEB = 1; - // CKF_KEYMANWEB_MODERN = 2; // used only by Typescript-based compiler const CERR_FATAL = $00008000; @@ -170,7 +169,6 @@ const function CompileKeyboardFile(kmnFile, kmxFile: PChar; FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; CallBack: TCompilerCallback): Integer; cdecl; // I4865 // I4866 function CompileKeyboardFileToBuffer(kmnFile: PChar; buf: PFILE_KEYBOARD; CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; CallBack: TCompilerCallback; Target: Integer): Integer; cdecl; // I4865 // I4866 -function CompileKeyboardFileEx(kmnFile, kmxfile: PChar; FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; CallBack: TCompilerCallback; Target: Integer): Integer; // I4865 // I4866 function Compiler_Diagnostic(mode: Integer): Integer; procedure Compiler_Diagnostic_Console(mode: Integer); @@ -203,18 +201,13 @@ var HKMCmpDll: THandle = 0; type - TCompileKeyboardFile = function (kmnFile, kmxFile: PAnsiChar; - FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; // I3310 // I4865 // I4866 + TCompileKeyboardFile = function (kmnFile, kmxFile: PAnsiChar; FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; // I3310 // I4865 // I4866 CallBack: TCompilerCallback): Integer; cdecl; // TODO: K9: Convert to Unicode TCompileKeyboardFileToBuffer = function (kmnFile: PAnsiChar; buf: PFILE_KEYBOARD; // I3310 CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; // I4865 // I4866 CallBack: TCompilerCallback; Target: Integer): Integer; cdecl; // TODO: K9: Convert to Unicode - TCompileKeyboardFileEx = function (kmnFile, kmxFile: PAnsiChar; - FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; - CallBack: TCompilerCallback; Target: Integer): Integer; cdecl; // TODO: K9: Convert to Unicode - TSetCompilerOptions = function (options: PCOMPILER_OPTIONS): BOOL; cdecl; function LoadCompiler(CallBack: TCompilerCallback = nil): Boolean; @@ -311,26 +304,6 @@ begin Result := ckf(PAnsiChar(AnsiString(kmnFile)), buf, CompilerWarningsAsErrors, WarnDeprecatedCode, Callback, Target); // I3310 // I4865 // I4866 end; -function CompileKeyboardFileEx(kmnFile, kmxfile: PChar; FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode: BOOL; CallBack: TCompilerCallback; Target: Integer): Integer; // I4865 // I4866 -var - ckf: TCompileKeyboardFileEx; -begin - //Result := 0; - - if not LoadCompiler(Callback) then Exit(-1); - - @ckf := GetProcAddress(HKMCmpDll, 'CompileKeyboardFileEx'); - if not Assigned(@ckf) then - begin - Callback(0, $8000, PAnsiChar(AnsiString('Could not access the compiler. Check that '+kmcmpdll_lib+' is in the program directory '+ // I4706 - 'and that it is not corrupt.'#13#10+'Windows error message: '+SysErrorMessage(GetLastError)))); - Result := -1; - Exit; - end; - - Result := ckf(PAnsiChar(AnsiString(kmnFile)), PAnsiChar(AnsiString(kmxfile)), FSaveDebug, CompilerWarningsAsErrors, WarnDeprecatedCode, Callback, Target); // I3310 // I4865 // I4866 -end; - type TKeyman_Diagnostic = procedure(mode: Integer); cdecl; diff --git a/developer/src/kmcmpdll/Compiler.cpp b/developer/src/kmcmpdll/Compiler.cpp index 23e23e791b..100e43fc5b 100644 --- a/developer/src/kmcmpdll/Compiler.cpp +++ b/developer/src/kmcmpdll/Compiler.cpp @@ -299,11 +299,6 @@ extern "C" BOOL __declspec(dllexport) SetCompilerOptions(PCOMPILER_OPTIONS optio } extern "C" BOOL __declspec(dllexport) CompileKeyboardFile(PSTR pszInfile, PSTR pszOutfile, BOOL ASaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc) // I4865 // I4866 -{ - return CompileKeyboardFileEx(pszInfile, pszOutfile, ASaveDebug, ACompilerWarningsAsErrors, AWarnDeprecatedCode, pMsgProc, CKF_KEYMAN); -} - -extern "C" BOOL __declspec(dllexport) CompileKeyboardFileEx(PSTR pszInfile, PSTR pszOutfile, BOOL ASaveDebug, BOOL ACompilerWarningsAsErrors, BOOL AWarnDeprecatedCode, CompilerMessageProc pMsgProc, int Target) // I4865 // I4866 { HANDLE hInfile = INVALID_HANDLE_VALUE, hOutfile = INVALID_HANDLE_VALUE; BOOL err; @@ -314,7 +309,7 @@ extern "C" BOOL __declspec(dllexport) CompileKeyboardFileEx(PSTR pszInfile, PSTR FCompilerWarningsAsErrors = ACompilerWarningsAsErrors; // I4865 FWarnDeprecatedCode = AWarnDeprecatedCode; // I4866 - CompileTarget = Target; + CompileTarget = CKF_KEYMAN; if (!pMsgProc || !pszInfile || !pszOutfile) SetError(CERR_BadCallParams); diff --git a/developer/src/kmcomp/kmcomp.dproj b/developer/src/kmcomp/kmcomp.dproj index 9bb6af3b5c..36c16e3535 100644 --- a/developer/src/kmcomp/kmcomp.dproj +++ b/developer/src/kmcomp/kmcomp.dproj @@ -109,7 +109,7 @@ RELEASE;$(DCC_Define)
- \Projects\keyman\keyboards\release\k\khmer_angkor\source\khmer_angkor.kmn c:\temp\ka.js + c:\temp\foo.kps -schema-path C:\Projects\keyman\app\common\schemas\kps\ true 2 1033 From eab503a8292f2b9e52a9ff64158815013a5c2561 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 5 Jun 2023 16:19:41 +0700 Subject: [PATCH 17/21] chore(developer): roll back CKF_KEYMANWEB_MODERN, not needed --- developer/src/kmcmplib/include/kmcmplibapi.h | 3 +-- developer/src/kmcmplib/src/Compiler.cpp | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/developer/src/kmcmplib/include/kmcmplibapi.h b/developer/src/kmcmplib/include/kmcmplibapi.h index 2b28aaa2d3..0b41af6990 100644 --- a/developer/src/kmcmplib/include/kmcmplibapi.h +++ b/developer/src/kmcmplib/include/kmcmplibapi.h @@ -19,8 +19,7 @@ /* Compile target */ #define CKF_KEYMAN 0 -#define CKF_KEYMANWEB 1 // For legacy kmcomp compiler, to be deprecated and removed -#define CKF_KEYMANWEB_MODERN 2 // For Typescript kmc-kmw compiler +#define CKF_KEYMANWEB 1 struct KMCMP_COMPILER_OPTIONS { bool saveDebug; diff --git a/developer/src/kmcmplib/src/Compiler.cpp b/developer/src/kmcmplib/src/Compiler.cpp index 322230a3e9..e5d5f94cbc 100644 --- a/developer/src/kmcmplib/src/Compiler.cpp +++ b/developer/src/kmcmplib/src/Compiler.cpp @@ -1212,7 +1212,7 @@ KMX_DWORD CheckStatementOffsets(PFILE_KEYBOARD fk, PFILE_GROUP gp, PKMX_WCHAR co // Due to a limitation in earlier versions of KeymanWeb, the minimum version // for context() referring to notany() is 14.0. See #917 for details. - if (kmcmp::CompileTarget != CKF_KEYMAN) { + if (kmcmp::CompileTarget == CKF_KEYMANWEB) { for (q = context, i = 1; *q && i < contextOffset; q = incxstr(q), i++); if (*q == UC_SENTINEL && *(q + 1) == CODE_NOTANY) { VERIFY_KEYBOARD_VERSION(fk, VERSION_140, CERR_140FeatureOnlyContextAndNotAnyWeb); @@ -1665,7 +1665,7 @@ int LineTokenType(PKMX_WCHAR *str) /* Test KeymanWeb, Keyman and KeymanOnly prefixes */ if (kmcmp::CompileTarget == CKF_KEYMAN && lpt == lptKeymanWebOnly) return T_BLANK; - if (kmcmp::CompileTarget != CKF_KEYMAN && lpt == lptKeymanOnly) return T_BLANK; + if (kmcmp::CompileTarget == CKF_KEYMANWEB && lpt == lptKeymanOnly) return T_BLANK; while (iswspace(*p)) p++; @@ -2146,7 +2146,7 @@ KMX_DWORD GetXStringImpl(PKMX_WCHAR tstr, PFILE_KEYBOARD fk, PKMX_WCHAR str, KMX // in the web target platform, even if there are platform() rules excluding this possibility. In that (rare) situation, the keyboard developer should simply specify // the &version to be 9.0 or whatever to avoid this behaviour. if (sFlag & (LCTRLFLAG | LALTFLAG | RCTRLFLAG | RALTFLAG | CAPITALFLAG | NOTCAPITALFLAG | NUMLOCKFLAG | NOTNUMLOCKFLAG | SCROLLFLAG | NOTSCROLLFLAG) && - kmcmp::CompileTarget != CKF_KEYMAN && + kmcmp::CompileTarget == CKF_KEYMANWEB && fk->dwFlags & KF_AUTOMATICVERSION) { VERIFY_KEYBOARD_VERSION(fk, VERSION_100, 0); } From 91f985de03ac9a349a7d3686845dd56fcde04d10 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 5 Jun 2023 16:33:38 +0700 Subject: [PATCH 18/21] chore(developer): cleanup build.sh --- developer/src/kmc-kmw/build.sh | 69 +++++++++++++++------------------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/developer/src/kmc-kmw/build.sh b/developer/src/kmc-kmw/build.sh index aa712d10ce..1e43793b16 100755 --- a/developer/src/kmc-kmw/build.sh +++ b/developer/src/kmc-kmw/build.sh @@ -1,31 +1,26 @@ #!/usr/bin/env bash -# -# Compiles the kmc KeymanWeb keyboard compiler. -# - -# Exit on command failure and when using unset variables: -set -eu - ## START STANDARD BUILD SCRIPT INCLUDE # adjust relative paths as necessary -THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" -. "$(dirname "$THIS_SCRIPT")/../../../resources/build/build-utils.sh" +THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")" +. "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh" ## END STANDARD BUILD SCRIPT INCLUDE cd "$THIS_SCRIPT_PATH" . "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" +. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh" builder_describe "Build Keyman kmc KMW Keyboard Compiler module" \ - "@/common/web/keyman-version" \ "@/common/web/types" \ "@/developer/src/kmc-kmn" \ "configure" \ "build" \ "clean" \ "test" \ + "pack build a local .tgz pack for testing" \ "publish publish to npm" \ "--dry-run,-n don't actually publish, just dry run" + builder_describe_outputs \ configure /node_modules \ build build/src/main.js @@ -34,42 +29,40 @@ builder_parse "$@" #------------------------------------------------------------------------------------------------------------------- -if builder_start_action clean; then - rm -rf ./build/ ./tsconfig.tsbuildinfo - builder_finish_action success clean -else - # We need the schema file at runtime and bundled, so always copy it for all actions except `clean` +function copy_schema() { + # We need the schema file at runtime and bundled, so always copy it for all + # actions except `clean` and `configure` mkdir -p "$THIS_SCRIPT_PATH/build/src/" cp "$KEYMAN_ROOT/common/schemas/keyman-touch-layout/keyman-touch-layout.spec.json" "$THIS_SCRIPT_PATH/build/src/" cp "$KEYMAN_ROOT/common/schemas/kvks/kvks.schema.json" "$THIS_SCRIPT_PATH/build/src/" -fi +} -#------------------------------------------------------------------------------------------------------------------- - -if builder_start_action configure; then - verify_npm_setup - builder_finish_action success configure -fi - -#------------------------------------------------------------------------------------------------------------------- - -if builder_start_action build; then +function do_build() { + copy_schema npm run build - builder_finish_action success build -fi +} -#------------------------------------------------------------------------------------------------------------------- - -if builder_start_action test; then +function do_test() { # TODO: add c8 for coverage + copy_schema npm test - builder_finish_action success test -fi +} + +function do_publish() { + copy_schema + builder_publish_to_npm +} + +function do_pack() { + copy_schema + builder_publish_to_pack +} #------------------------------------------------------------------------------------------------------------------- -if builder_start_action publish; then - . "$KEYMAN_ROOT/resources/build/npm-publish.inc.sh" - npm_publish - builder_finish_action success publish -fi +builder_run_action clean rm -rf ./build/ ./tsconfig.tsbuildinfo +builder_run_action configure verify_npm_setup +builder_run_action build do_build +builder_run_action test do_test +builder_run_action pack do_pack +builder_run_action publish do_publish From eaf7a6b6287561daafff242f19a712c931599b46 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Mon, 5 Jun 2023 16:34:23 +0700 Subject: [PATCH 19/21] chore(developer): merge changed interfaces in compiler --- common/web/types/src/main.ts | 2 +- .../src/kmc-kmw/src/compiler/write-compiled-keyboard.ts | 5 ++--- developer/src/kmc-kmw/test/test-compiler-manual.ts | 8 ++++---- developer/src/kmc-kmw/test/test-compiler.ts | 8 ++++---- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/common/web/types/src/main.ts b/common/web/types/src/main.ts index 9e65ccb99a..ddaa318d3e 100644 --- a/common/web/types/src/main.ts +++ b/common/web/types/src/main.ts @@ -7,7 +7,7 @@ export { KmxFileReader } from './kmx/kmx-file-reader.js'; export * as VisualKeyboard from './kvk/visual-keyboard.js'; export { default as KMXPlusBuilder} from './kmx/kmx-plus-builder/kmx-plus-builder.js'; export { default as KvkFileReader } from './kvk/kvk-file-reader.js'; -export { default as KvksFileReader, KVKSParseError } from './kvk/kvks-file-reader.js'; +export { default as KvksFileReader } from './kvk/kvks-file-reader.js'; export { default as KvkFileWriter } from './kvk/kvk-file-writer.js'; export * as KvkFile from './kvk/kvk-file.js'; export * as KvksFile from './kvk/kvk-file.js'; diff --git a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts index 7e89aa7cdd..082c7a1881 100644 --- a/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts +++ b/developer/src/kmc-kmw/src/compiler/write-compiled-keyboard.ts @@ -1,4 +1,4 @@ -import { KVKSParseError, VisualKeyboard } from "@keymanapp/common-types"; +import { VisualKeyboard } from "@keymanapp/common-types"; import { KMX, CompilerCallbacks, KvkFileReader, KvksFileReader } from "@keymanapp/common-types"; import { ExpandSentinel, incxstr, xstrlen } from "../util/util.js"; // import { KEY, KEYBOARD, KMX.KMXFile, STORE } from "../../../../../common/web/types/src/kmx/kmx.js"; @@ -202,8 +202,7 @@ export function WriteCompiledKeyboard(callbacks: CompilerCallbacks, kmnfile: str let reader = new KvksFileReader(); let source = reader.read(callbacks.loadFile(path)); reader.validate(source, callbacks.loadSchema("kvks")); // TODO: handle exceptions - let errors: KVKSParseError[]; - kvk = reader.transform(source, errors); + kvk = reader.transform(source); // TODO: log errors } else { diff --git a/developer/src/kmc-kmw/test/test-compiler-manual.ts b/developer/src/kmc-kmw/test/test-compiler-manual.ts index 9f4f5ea4db..39869657f4 100644 --- a/developer/src/kmc-kmw/test/test-compiler-manual.ts +++ b/developer/src/kmc-kmw/test/test-compiler-manual.ts @@ -2,7 +2,7 @@ import { dirname } from 'path'; import { fileURLToPath } from 'url'; import fs from 'fs'; import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; -import { Compiler } from '@keymanapp/kmc-kmn'; +import { KmnCompiler } from '@keymanapp/kmc-kmn'; import { KMX, KmxFileReader } from '@keymanapp/common-types'; import { WriteCompiledKeyboard } from '../src/compiler/write-compiled-keyboard.js'; import { extractTouchLayout } from './util.js'; @@ -20,14 +20,14 @@ if(fs.existsSync(testOutfile)) { const callbacks = new TestCompilerCallbacks(); -const kmxCompiler = new Compiler(); -if(!await kmxCompiler.init()) { +const kmnCompiler = new KmnCompiler(); +if(!await kmnCompiler.init(callbacks)) { console.error('kmx compiler failed to init'); process.exit(1); } // TODO: runToMemory, add option to kmxCompiler to store debug-data for conversion to .js (e.g. store metadata, group readonly metadata, etc) -if(!kmxCompiler.run(infile, outfile, callbacks, { +if(!kmnCompiler.run(infile, outfile, { shouldAddCompilerVersion: false, saveDebug: true, target: 'js' diff --git a/developer/src/kmc-kmw/test/test-compiler.ts b/developer/src/kmc-kmw/test/test-compiler.ts index 7332d71bda..7f086ca0ad 100644 --- a/developer/src/kmc-kmw/test/test-compiler.ts +++ b/developer/src/kmc-kmw/test/test-compiler.ts @@ -6,7 +6,7 @@ import { dirname } from 'path'; import { fileURLToPath } from 'url'; import fs from 'fs'; import { TestCompilerCallbacks } from '@keymanapp/developer-test-helpers'; -import { Compiler } from '@keymanapp/kmc-kmn'; +import { KmnCompiler } from '@keymanapp/kmc-kmn'; import { KMX, KmxFileReader } from '@keymanapp/common-types'; import { extractTouchLayout } from './util.js'; @@ -35,11 +35,11 @@ describe('Compiler class', function() { fs.unlinkSync(testOutfile); } - const kmxCompiler = new Compiler(); - assert.isTrue(await kmxCompiler.init()); + const kmnCompiler = new KmnCompiler(); + assert.isTrue(await kmnCompiler.init(callbacks)); // TODO: runToMemory, add option to kmxCompiler to store debug-data for conversion to .js (e.g. store metadata, group readonly metadata, visual keyboard source filename, etc) - assert.isTrue(kmxCompiler.run(infile, outfile, callbacks, { + assert.isTrue(kmnCompiler.run(infile, outfile, { shouldAddCompilerVersion: false, saveDebug: true, target: 'js' From db6d8033a026d228a62714c9a996a9ef0386f9f6 Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Tue, 6 Jun 2023 14:39:04 +0700 Subject: [PATCH 20/21] chore(developer): npm install --- package-lock.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package-lock.json b/package-lock.json index 568c70e2b3..fbd15530d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1032,6 +1032,7 @@ } }, "developer/src/kmc-kmw": { + "name": "@keymanapp/kmc-kmw", "license": "MIT", "dependencies": { "@keymanapp/common-types": "*", From 6421a1f6f40e7e132c6313a84e81ff72b189030b Mon Sep 17 00:00:00 2001 From: Marc Durdin Date: Thu, 8 Jun 2023 17:34:37 +1000 Subject: [PATCH 21/21] chore: Apply suggestions from code review Co-authored-by: Joshua Horton --- developer/src/kmc-kmw/src/compiler/javascript-strings.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts index 2504781b9b..731e837767 100644 --- a/developer/src/kmc-kmw/src/compiler/javascript-strings.ts +++ b/developer/src/kmc-kmw/src/compiler/javascript-strings.ts @@ -123,13 +123,10 @@ export function JavaScript_String(ch: number): string { // I2242 case 10: return '\\n'; case 13: return '\\r'; } - if(ch < 9) { - return '\\x0'+ch.toString(16).toUpperCase(); - } else { - return '\\x'+ch.toString(16).toUpperCase(); - } + return '\\x' + zeroPadHex(ch, 2); } else { + // Note: unpaired surrogates will be maintained return String.fromCodePoint(ch); } } @@ -776,7 +773,6 @@ function CheckStoreForInvalidFunctions(fk: KMX.KEYBOARD, key: KMX.KEY, store: KM // Used when targeting versions prior to 10.0, before the introduction of FullContextMatch/KFCM. function JavaScript_CompositeContextValue(fk: KMX.KEYBOARD, fkp: KMX.KEY, pwsz: string): string { - // Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions // var // StartQuotes, Len, Cur: Integer; // InQuotes: Boolean;