Merge branch 'master' into feat/core/9121-more-vars-epic-ldml

This commit is contained in:
Steven R. Loomis 2023-10-07 11:36:07 -05:00 • committed by GitHub
commit 505a45e933
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
98 changed files with 461 additions and 3347 deletions

View file

@ -21,9 +21,7 @@
"exports": {
".": "./build/obj/index.js",
"./lib": {
"types": "./build/lib/index.d.ts",
"import": "./build/lib/index.mjs",
"require": "./build/lib/index.cjs"
"types": "./build/lib/index.d.ts"
},
"./obj/*.js": "./build/obj/*.js"
},

View file

@ -19,8 +19,7 @@
"exports": {
".": "./build/obj/index.js",
"./lib": {
"import": "./build/lib/index.mjs",
"require": "./build/lib/index.cjs"
"types": "./build/lib/index.d.ts"
},
"./obj/*.js": "./build/obj/*.js"
},

View file

@ -1,28 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<!-- Set the viewport width to match iOS device widths -->
<!-- <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no" /> -->
<meta name="viewport" content="width=device-width,user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- Enable IE9 Standards mode -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>LMLayer Testing</title>
<style type='text/css'>
body {padding-left:20px;margin-left:12px; font-family:Tahoma,Helvetica}
h1 {color: #800;margin-left:10px;}
h2 {color: #008;margin-left:20px;}
</style>
</head>
<body>
<h1>Language-Modeling Layer module testing</h1>
<h2><a href="./simple-webworker">A simple basic WebWorker.</a></h2> Designed as a baseline functionality test we can run against various platforms as a first-stage canary of sorts.
<h2><a href="./one-stage-embedded-webworker">An embedded WebWorker prototype.</a></h2> A prototype for directly embedding a WebWorker's code within a "master" script.
<h2><a href="./two-stage-embedded-webworker">A better embedded WebWorker prototype.</a></h2> A prototype for two-stage compilation of a master/slave main-script/WebWorker pair.
<h2><a href="./post-blob-webworker/">Sending code via a Blob URI</a></h2> A prototype for sending code over to a WebWorker via a Blob URI reference.
</body>
</html>

View file

@ -1,2 +0,0 @@
main.js
main.js.map

View file

@ -1,54 +0,0 @@
#!/usr/bin/env bash
#
# Compiles the Language Modeling Layer for common use in predictive text and autocorrective applications.
# Designed for optimal compatibility with the Keyman Suite.
#
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
. "${THIS_SCRIPT%/*}/../../../../resources/build/build-utils.sh"
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
## END STANDARD BUILD SCRIPT INCLUDE
display_usage ( ) {
echo "build.sh [-clean]"
echo
echo " -clean to erase pre-existing build products before a re-build"
}
SOURCE="testing/one-stage-embedded-webworker"
echo "Node.js + dependencies check"
npm install --no-optional
if [ $? -ne 0 ]; then
builder_die "Build environment setup error detected! Please ensure Node.js is installed!"
fi
# A nice, extensible method for -clean operations. Add to this as necessary.
clean ( ) {
rm -rf "./*.js"
if [ $? -ne 0 ]; then
builder_die "Failed to erase the prior build."
fi
}
# Process command-line arguments
while [[ $# -gt 0 ]] ; do
key="$1"
case $key in
-clean)
clean
;;
esac
shift # past the processed argument
done
npm run tsc -- -p $SOURCE/tsconfig.json
if [ $? -ne 0 ]; then
builder_die "Compilation failed."
fi
echo "Typescript compilation successful."

View file

@ -1,42 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<!-- Set the viewport width to match phone and tablet device widths -->
<meta name="viewport" content="width=device-width,user-scalable=no" />
<!-- Allow KeymanWeb to be saved to the iPhone home screen -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- Enable IE9 Standards mode -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Embedded WebWorker test</title>
<!-- Your page CSS -->
<style type='text/css'>
body {font-family: Tahoma,helvetica;}
h3 {font-size: 1em;font-weight:normal;color: darkred; margin-bottom: 4px}
.test {font-size: 1.5em; width:80%; min-height:30px; border: 1px solid gray;}
#KeymanWebControl {width:50%;min-width:600px;}
</style>
<script src="main.js"></script>
</head>
<!-- Sample page HTML -->
<body>
<h2>LM Layer Testing - One-Stage Embedded WebWorkers</h2>
<p>This page serves as a prototype for embedding a WebWorker's code within its "master" script
across the TypeScript transpilation boundary.</p>
<input type='text' id='txtFeedback' value="No clicks yet." readonly></input> <br>
<script>
var txtFeedback = document.getElementById("txtFeedback");
txtFeedback.value = "No clicks yet.";
</script>
<input type='button' id='btnInput' onclick='canaryWorker.postMessage("Hello.");' value='Message the WebWorker.' />
<h3><a href="../index.html">Return to testing home page</a></h3>
</body>
</html>

View file

@ -1,52 +0,0 @@
// Useful for passing class constructors
type Workable<T> = {
new (...args: any[]): T;
// Requires a static implementation.
onmessage(e: any): void;
};
class A {
a(x: number, y: number):number {
return x + y;
}
}
var WorkerGlobals = {
counter: 0,
a: A
}
class WorkerCore {
static WorkerGlobals = WorkerGlobals;
//static counter: number;
static onmessage(e: any) {
WorkerGlobals.counter++;
console.log("Message received from main page: ", e.data);
// Forces TypeScript to interpret this line as plain JavaScript, as it uses a non-Worker definition.
// @ts-ignore
postMessage(WorkerGlobals.counter);
}
}
function createWorkerFromClasses(globals: object, fn: Workable<object>): Worker {
var sep = ";\n";
let glb = "var WorkerGlobals = " + JSON.stringify(globals);
let wc = "var onmessage = " + fn.onmessage.toString();
var blob = new Blob([glb, sep, wc], { type: 'text/javascript' });
let url = URL.createObjectURL(blob);
return new Worker(url);
}
var canaryWorker = createWorkerFromClasses(WorkerGlobals, WorkerCore);
canaryWorker.onmessage = function(e) {
var counter = e.data; // Number of times the WebWorker has been messaged.
console.log("Received message from the WebWorker: " + e.data);
var txtFeedback = <HTMLInputElement>document.getElementById("txtFeedback");
txtFeedback.value = counter + " click(s)";
}

View file

@ -1,13 +0,0 @@
{
"compilerOptions": {
"allowJs": false,
"module": "none",
"outDir": "./",
"inlineSources": true,
"sourceMap": true,
"target": "es5"
},
"files" : [
"main.ts"
]
}

View file

@ -1,5 +0,0 @@
// receive a message and execute its uri
onmessage = function (e) {
let uri = e.data.uri;
importScripts(uri);
};

View file

@ -1,72 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<!-- Set the viewport width to match phone and tablet device widths -->
<meta name="viewport" content="width=device-width,user-scalable=no" />
<!-- Allow KeymanWeb to be saved to the iPhone home screen -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- Enable IE9 Standards mode -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Blob URI test</title>
<!-- Your page CSS -->
<style type='text/css'>
body {font-family: Tahoma,helvetica;}
h3 {font-size: 1em;font-weight:normal;color: darkred; margin-bottom: 4px}
.test {font-size: 1.5em; width:80%; min-height:30px; border: 1px solid gray;}
#KeymanWebControl {width:50%;min-width:600px;}
</style>
<script>
if (window.Worker) {
var canaryWorker = new Worker('canaryWorker.js');
canaryWorker.onmessage = function(e) {
var message = e.data; // Number of times the WebWorker has been messaged.
console.log("Received message from the WebWorker: " + e.data);
var txtFeedback = document.getElementById("txtFeedback");
txtFeedback.value = message;
}
} else {
console.error("WebWorkers are not supported in this browser!");
}
</script>
</head>
<!-- Sample page HTML -->
<body>
<h2>LM Layer Testing - Sending a function to a WebWorker via a Blob URI test</h2>
<p>This page sends a function over to the Worker via a Blob URI, and
expects the function to reply back.
</p>
<input type='text' id='txtFeedback' value="Haven't heard back yet" readonly> <br>
<script>
var txtFeedback = document.getElementById("txtFeedback");
txtFeedback.value = "Have not heard back from worker";
function sendCode () {
function payload () {
postMessage('Hello, from the blobified code!');
}
// Create an immediately-invoked function expression... to immediately
// invoke the code!
let iife = ['(', payload.toString(), '())'];
let blob = new Blob(iife, { type: 'text/javascript' });
let uri = URL.createObjectURL(blob);
// Go!
canaryWorker.postMessage({ uri: uri });
}
</script>
<input type='button' id='btnInput' onclick='sendCode()' value='Send the source code!' />
<h3><a href="../index.html">Return to testing home page</a></h3>
</body>
</html>

View file

@ -1,9 +0,0 @@
var counter = 0;
onmessage = function(e) {
counter++;
console.log("Message received from main page: ", e.data);
postMessage(counter);
}

View file

@ -1,55 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<!-- Set the viewport width to match phone and tablet device widths -->
<meta name="viewport" content="width=device-width,user-scalable=no" />
<!-- Allow KeymanWeb to be saved to the iPhone home screen -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- Enable IE9 Standards mode -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Basic WebWorker test</title>
<!-- Your page CSS -->
<style type='text/css'>
body {font-family: Tahoma,helvetica;}
h3 {font-size: 1em;font-weight:normal;color: darkred; margin-bottom: 4px}
.test {font-size: 1.5em; width:80%; min-height:30px; border: 1px solid gray;}
#KeymanWebControl {width:50%;min-width:600px;}
</style>
<script>
if(window.Worker) {
var canaryWorker = new Worker('canaryWorker.js');
canaryWorker.onmessage = function(e) {
var counter = e.data; // Number of times the WebWorker has been messaged.
console.log("Received message from the WebWorker: " + e.data);
var txtFeedback = document.getElementById("txtFeedback");
txtFeedback.value = counter + " click(s)";
}
} else {
console.error("WebWorkers are not supported in this browser!");
}
</script>
</head>
<!-- Sample page HTML -->
<body>
<h2>LM Layer Testing - basic WebWorker canary</h2>
<p>This page uses a simple WebWorker useful for ensuring functionality on various platforms.</p>
<input type='text' id='txtFeedback' value="No clicks yet." readonly></input> <br>
<script>
var txtFeedback = document.getElementById("txtFeedback");
txtFeedback.value = "No clicks yet.";
</script>
<input type='button' id='btnInput' onclick='canaryWorker.postMessage("Hello.");' value='Message the WebWorker.' />
<h3><a href="../index.html">Return to testing home page</a></h3>
</body>
</html>

View file

@ -1,2 +0,0 @@
**/*.js
**/*.js.map

View file

@ -1,68 +0,0 @@
#!/usr/bin/env bash
#
# Compiles the Language Modeling Layer for common use in predictive text and autocorrective applications.
# Designed for optimal compatibility with the Keyman Suite.
#
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
. "${THIS_SCRIPT%/*}/../../../../resources/build/build-utils.sh"
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
## END STANDARD BUILD SCRIPT INCLUDE
display_usage ( ) {
echo "build.sh [-clean]"
echo
echo " -clean to erase pre-existing build products before a re-build"
}
SOURCE="testing/two-stage-embedded-webworker"
COMPILED_WORKER="worker.js"
EMBEDDED_WORKER="embedded_worker.js"
echo "Node.js + dependencies check"
npm install --no-optional
if [ $? -ne 0 ]; then
builder_die "Build environment setup error detected! Please ensure Node.js is installed!"
fi
# A nice, extensible method for -clean operations. Add to this as necessary.
clean ( ) {
rm -rf "./*.js"
if [ $? -ne 0 ]; then
builder_die "Failed to erase the prior build."
fi
}
# Process command-line arguments
while [[ $# -gt 0 ]] ; do
key="$1"
case $key in
-clean)
clean
;;
esac
shift # past the processed argument
done
npm run tsc -- -p $SOURCE/worker/tsconfig.json
if [ $? -ne 0 ]; then
builder_die "Worker compilation failed."
fi
rm $EMBEDDED_WORKER &> /dev/null
echo "var LMLayerWorker = function() {" >> $EMBEDDED_WORKER
cat $COMPILED_WORKER >> $EMBEDDED_WORKER
echo "" >> $EMBEDDED_WORKER
echo "}" >> $EMBEDDED_WORKER
npm run tsc -- -p $SOURCE/tsconfig.json
if [ $? -ne 0 ]; then
builder_die "Final compilation failed."
fi
echo "Typescript compilation successful."

View file

@ -1,42 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<!-- Set the viewport width to match phone and tablet device widths -->
<meta name="viewport" content="width=device-width,user-scalable=no" />
<!-- Allow KeymanWeb to be saved to the iPhone home screen -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<!-- Enable IE9 Standards mode -->
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Embedded WebWorker test</title>
<!-- Your page CSS -->
<style type='text/css'>
body {font-family: Tahoma,helvetica;}
h3 {font-size: 1em;font-weight:normal;color: darkred; margin-bottom: 4px}
.test {font-size: 1.5em; width:80%; min-height:30px; border: 1px solid gray;}
#KeymanWebControl {width:50%;min-width:600px;}
</style>
<script src="main.js"></script>
</head>
<!-- Sample page HTML -->
<body>
<h2>LM Layer Testing - One-Stage Embedded WebWorkers</h2>
<p>This page serves as a prototype for embedding a WebWorker's code within its "master" script
across the TypeScript transpilation boundary.</p>
<input type='text' id='txtFeedback' value="No clicks yet." readonly></input> <br>
<script>
var txtFeedback = document.getElementById("txtFeedback");
txtFeedback.value = "No clicks yet.";
</script>
<input type='button' id='btnInput' onclick='canaryWorker.postMessage("Hello.");' value='Message the WebWorker.' />
<h3><a href="../index.html">Return to testing home page</a></h3>
</body>
</html>

View file

@ -1,30 +0,0 @@
// Provides the final source for our compiled WebWorker within a wrapping function.
/// <reference path="embedded_worker.js" />
function createWorker(fn: Function): Worker {
var str_fn = fn.toString();
// We now unwrap our WebWorker from its function.
var str_lines = str_fn.split("\n");
var blob_lines = []
for(var i=1; i < str_lines.length -1; i++) {
blob_lines.push(str_lines[i] + "\n");
}
// Unwrapping complete.
var blob = new Blob(blob_lines, { type: 'text/javascript' });
let url = URL.createObjectURL(blob);
return new Worker(url);
}
var canaryWorker = createWorker(LMLayerWorker);
canaryWorker.onmessage = function(e) {
var counter = e.data; // Number of times the WebWorker has been messaged.
console.log("Received message from the WebWorker: " + e.data);
var txtFeedback = <HTMLInputElement>document.getElementById("txtFeedback");
txtFeedback.value = counter + " click(s)";
}

View file

@ -1,13 +0,0 @@
{
"compilerOptions": {
"allowJs": true,
"module": "none",
"outFile": "./main.js",
"inlineSources": true,
"inlineSourceMap": true,
"target": "es5"
},
"files" : [
"main.ts"
]
}

View file

@ -1,9 +0,0 @@
var counter = 0;
onmessage = function(e) {
counter++;
console.log("Message received from main page: ", e.data);
postMessage(counter);
}

View file

@ -1,11 +0,0 @@
{
"compilerOptions": {
"allowJs": false,
"module": "none",
"outFile": "../worker.js",
"inlineSources": true,
"sourceMap": true,
"lib": ["webworker", "es6"],
"target": "es5"
}
}

View file

@ -1,11 +1,4 @@
#!/usr/bin/env bash
#
# Builds hextobin.js
#
# Exit on command failure and when using unset variables:
set -eu
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
@ -22,21 +15,10 @@ cd "$THIS_SCRIPT_PATH"
builder_describe "Build hextobin" clean configure build
builder_describe_outputs \
configure /node_modules \
build build/index.js
build /common/tools/hextobin/build/index.js
builder_parse "$@"
if builder_start_action clean; then
npm run clean
builder_finish_action success clean
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
builder_run_action clean rm -rf build/ node_modules/
builder_run_action configure verify_npm_setup
builder_run_action build tsc --build

View file

@ -1,11 +1,11 @@
#!/usr/bin/env node
import * as fs from 'fs';
import * as rd from 'readline';
import * as program from 'commander';
import { Command } from 'commander';
import hextobin from './index.js';
let inputFilename: string = "";
let outputFilename: string = "";
const program = new Command();
program
.description(
`Will convert the input file which is a hex dump to the output file. Hex dump can contain
@ -43,6 +43,4 @@ function exitDueToUsageError(message: string): never {
return process.exit(64); // SysExits.EX_USAGE
}
import hextobin from './index';
hextobin(inputFilename, outputFilename, {silent: false});

View file

@ -1,6 +1,8 @@
{
"name": "@keymanapp/hextobin",
"description": "hextobin conversion tool",
"type": "module",
"private": true,
"keywords": [
"keyman",
"hex",
@ -14,14 +16,6 @@
"bin": {
"hextobin": "build/hextobin.js"
},
"scripts": {
"clean": "tsc -b --clean",
"build": "tsc -b"
},
"repository": {
"type": "git",
"url": "git+https://github.com/keymanapp/keyman.git"
},
"devDependencies": {
"@types/node": "^18.7.18"
}

View file

@ -1,19 +1,9 @@
{
"extends": "../../../tsconfig-base.json",
"compilerOptions": {
"composite": true,
"declaration": true,
"target": "ES2020",
"module": "CommonJS",
"moduleResolution": "node",
"rootDir": ".",
"outDir": "build/",
},
"exclude": [
"node_modules"
],
"files": [
"index.ts",
"hextobin.ts"
]
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"rootDir": ".",
"outDir": "build/"
},
"exclude": ["node_modules"],
"files": ["index.ts", "hextobin.ts"]
}

View file

@ -0,0 +1 @@
declare module 'convert-source-map';

View file

@ -1,12 +1,11 @@
{
"extends": "../../../tsconfig-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"allowJs": false,
"allowSyntheticDefaultImports": true,
"declaration": true,
"module": "es6",
"moduleResolution": "node",
"sourceMap": false,
"inlineSourceMap": true,
"inlineSources": true,
"sourceRoot": "/common/tools/sourcemap-path-remapper/src",

View file

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.esm-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": "./",
"outDir": "build/",

View file

@ -1,22 +0,0 @@
/*
* Bundles @keymanapp/keyman-version as a single-file CommonJS module for components
* still in need of it.
*/
import esbuild from 'esbuild';
// Bundles to a compact ESModule
esbuild.buildSync({
entryPoints: ['build/version.inc.js'],
bundle: true,
sourcemap: true,
//minify: true, // No need to minify a module.
//keepNames: true,
format: "cjs",
// Sets 'common/web' as a root folder for module resolution;
// this allows the keyman-version import to resolve.
nodePaths: ['..'],
outfile: "build/version.inc.cjs",
tsconfig: 'tsconfig.json',
target: "es5"
});

View file

@ -1,11 +1,4 @@
#!/usr/bin/env bash
#
# Builds the include script for the current Keyman version.
#
# Exit on command failure and when using unset variables:
set -eu
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
@ -13,6 +6,7 @@ THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
## END STANDARD BUILD SCRIPT INCLUDE
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh"
# This script runs from its own folder
cd "$THIS_SCRIPT_PATH"
@ -25,8 +19,7 @@ builder_describe "Build the include script for current Keyman version" \
build \
"pack build a local .tgz pack for testing" \
"publish publish to npm" \
test \
--dry-run
test
builder_describe_outputs \
configure "/node_modules" \
@ -34,21 +27,7 @@ builder_describe_outputs \
builder_parse "$@"
if builder_start_action configure; then
verify_npm_setup
builder_finish_action success configure
fi
if builder_start_action clean; then
npm run clean
rm -f ./version.inc.ts
rm -f ./keyman-version.mts
rm -rf build
builder_finish_action success clean
fi
if builder_start_action build; then
function do_build() {
# Generate version.inc.ts
echo "
// Generated by common/web/keyman-version/build.sh
@ -72,22 +51,11 @@ export class KEYMAN_VERSION {
export default KEYMAN_VERSION;
" > ./version.inc.ts
tsc -b $builder_verbose
# kmlmc (the lexical model compiler) relies on a Node-based import, but after some of the earlier
# ES-modularization work, our main output's an ES module. Fortunately, esbuild can provide an easy stopgap.
tsc --build $builder_verbose
}
# Generates a CommonJS variant (in case other modules still need it).
node ./build-bundler.js
builder_finish_action success build
fi
if builder_start_action publish; then
. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh"
builder_publish_to_npm
builder_finish_action success publish
elif builder_start_action pack; then
. "$KEYMAN_ROOT/resources/build/build-utils-ci.inc.sh"
builder_publish_to_pack
builder_finish_action success pack
fi
builder_run_action clean rm -rf version.inc.ts keyman-version.mts build/
builder_run_action configure verify_npm_setup
builder_run_action build do_build
builder_run_action publish builder_publish_to_npm
builder_run_action pack builder_publish_to_pack

View file

@ -1,26 +1,15 @@
{
"name": "@keymanapp/keyman-version",
"description": "Keyman global version data",
"main": "./build/version.inc.cjs",
"exports": {
".": {
"import": "./build/version.inc.js",
"require": "./build/version.inc.cjs"
},
"./build/version.inc.cjs": "./build/version.inc.cjs"
".": "./build/version.inc.js"
},
"files": [
"/build/"
],
"scripts": {
"build": "echo 'Building @keymanapp/keyman-version' && tsc -b",
"clean": "tsc -b --clean",
"tsc": "tsc"
},
"license": "MIT",
"type": "module",
"devDependencies": {
"@types/node": "^20.4.1",
"typescript": "^4.9.5"
}
}

View file

@ -1,17 +1,12 @@
{
"extends": "../../../tsconfig-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"allowJs": false,
"declaration": true,
"module": "es6",
"sourceMap": true,
"outDir": "./build",
"lib": ["es6"],
"target": "es5",
"downlevelIteration": true,
"rootDir": "."
},
"include": [
"version.inc.ts"
]

View file

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"declaration": true,
"module": "none",

View file

@ -1,13 +1,22 @@
{
"extends": "../../../../tsconfig-base.json",
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
// TODO: These override /tsconfig.base.json settings, and so should be removed if possible,
// but existing code in web/ breaks some of these settinsg
"noImplicitThis": false,
"noImplicitReturns": false,
"noImplicitAny": false,
"strictFunctionTypes": false,
"noUnusedLocals": false,
"allowJs": true,
"allowSyntheticDefaultImports": true,
"baseUrl": "./",
"inlineSources": true,
"lib": ["es6", "dom"],
"module": "es6",
"moduleResolution": "Node16",
"outDir": "../build/obj",
"rootDir": "./",
"sourceMap": true,

View file

@ -64,9 +64,15 @@ export class MarkerParser {
public static readonly MAX_MARKER_INDEX = constants.marker_max_index;
/** Max count of markers */
public static readonly MAX_MARKER_COUNT = constants.marker_max_count;
private static anyMarkerMatch() : string {
const start = (`0000` + (this.MIN_MARKER_INDEX).toString(16)).slice(-4);
const end = (`0000` + (this.MAX_MARKER_INDEX).toString(16)).slice(-4);
return `${this.SENTINEL}${this.MARKER_CODE}[\\u${start}-\\u${end}]`;
}
/** Expression that matches any marker */
public static readonly ANY_MARKER_MATCH =
this.SENTINEL + this.MARKER_CODE + `[\\u0001-\\u${this.MAX_MARKER_INDEX.toString(16)}]`;
public static readonly ANY_MARKER_MATCH = MarkerParser.anyMarkerMatch();
/**
* Pattern for matching a marker reference, OR the special marker \m{.}

View file

@ -105,16 +105,20 @@ describe('Test of Pattern Parsers', () => {
)
);
// verify the matching behavior of these
assert.isTrue(new RegExp(MarkerParser.toSentinelString(`Q\\m{a}`, markers, true), 'u')
assert.isTrue(new RegExp(MarkerParser.toSentinelString(`^Q\\m{a}$`, markers, true), 'u')
.test(MarkerParser.toSentinelString(`Q\\m{a}`, markers, false)), `Q\\m{a} did not match`);
assert.isFalse(new RegExp(MarkerParser.toSentinelString(`Q\\m{a}`, markers, true), 'u')
assert.isFalse(new RegExp(MarkerParser.toSentinelString(`^Q\\m{a}$`, markers, true), 'u')
.test(MarkerParser.toSentinelString(`Q\\m{b}`, markers, false)), `Q\\m{a} should not match Q\\m{b}`);
assert.isTrue(new RegExp(MarkerParser.toSentinelString(`Q\\m{.}`, markers, true), 'u')
assert.isTrue(new RegExp(MarkerParser.toSentinelString(`^Q\\m{.}$`, markers, true), 'u')
.test(MarkerParser.toSentinelString(`Q\\m{a}`, markers, false)), `Q\\m{.} did not match Q\\m{a}`);
assert.isTrue(new RegExp(MarkerParser.toSentinelString(`Q\\m{.}`, markers, true), 'u')
assert.isTrue(new RegExp(MarkerParser.toSentinelString(`^Q\\m{.}$`, markers, true), 'u')
.test(MarkerParser.toSentinelString(`Q\\m{zz}`, markers, false)), `Q\\m{.} did not match Q\\m{zz} (max marker)`);
assert.isFalse(new RegExp(MarkerParser.toSentinelString(`Q\\m{.}`, markers, true), 'u')
assert.isFalse(new RegExp(MarkerParser.toSentinelString(`^Q\\m{.}$`, markers, true), 'u')
.test(MarkerParser.toSentinelString(`\\m{a}`, markers, false)), `Q\\m{.} did not match \\m{a}`);
assert.isTrue(new RegExp(MarkerParser.toSentinelString(`^\\m{.}$`, markers, true), 'u')
.test(MarkerParser.toSentinelString(`\\m{a}`, markers, false)), `\\m{.} did not match \\m{a}`);
assert.isFalse(new RegExp(MarkerParser.toSentinelString(`^\\m{.}$`, markers, true), 'u')
.test(MarkerParser.toSentinelString(`\\m{a}\\m{b}`, markers, false)), `\\m{.} did not match \\m{a}\\m{b}`);
});
it('should match some marker constants', () => {
assert.equal(constants.uc_sentinel, KMXFile.UC_SENTINEL);

View file

@ -1,5 +1,5 @@
{
"extends": "../../../../tsconfig.esm-base.json",
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"rootDir": ".",

View file

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.esm-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "build/src/",

View file

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.esm-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"declaration": true,

View file

@ -1,10 +1,8 @@
{
"extends": "../../../tsconfig-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"composite": true,
"declaration": true,
"module": "es2020",
"moduleResolution": "node",
"rootDir": ".",
"outDir": "build/",
},

View file

@ -1,5 +1,5 @@
{
"extends": "../../../../../tsconfig.esm-base.json",
"extends": "../../../../../tsconfig.base.json",
"compilerOptions": {
"rootDir": ".",

View file

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.esm-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "build/src/",

View file

@ -6,7 +6,6 @@
"rootDirs": ["./", "../src/"],
"outDir": "../build/test",
"esModuleInterop": true,
"moduleResolution": "node16",
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"paths": {

View file

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.esm-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "build/src/",

View file

@ -1,12 +1,10 @@
import 'mocha';
import {assert} from 'chai';
import x_hextobin from '@keymanapp/hextobin';
import hextobin from '@keymanapp/hextobin';
import { KMXBuilder } from '@keymanapp/common-types';
import {checkMessages, compileKeyboard, compilerTestCallbacks, compilerTestOptions, makePathToFixture} from './helpers/index.js';
import { LdmlKeyboardCompiler } from '../src/compiler/compiler.js';
const hextobin = (x_hextobin as any).default;
describe('compiler-tests', function() {
this.slow(500); // 0.5 sec -- json schema validation takes a while

View file

@ -1,11 +1,9 @@
import 'mocha';
import {assert} from 'chai';
import x_hextobin from '@keymanapp/hextobin';
import hextobin from '@keymanapp/hextobin';
import { KvkFileWriter } from '@keymanapp/common-types';
import {checkMessages, compilerTestOptions, compileVisualKeyboard, makePathToFixture} from './helpers/index.js';
const hextobin = (x_hextobin as any).default;
describe('visual-keyboard-compiler', function() {
this.slow(500); // 0.5 sec -- json schema validation takes a while

View file

@ -1,5 +1,5 @@
{
"extends": "../../../tsconfig.esm-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "build/src/",

View file

@ -6,7 +6,6 @@
"rootDirs": ["./", "../src/"],
"outDir": "../build/test",
"esModuleInterop": true,
"moduleResolution": "node16",
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"paths": {

View file

@ -1,5 +1,5 @@
import { assert } from "chai";
import defaultWordBreaker from './wordbreakers/default-wordbreaker-esm.js';
import defaultWordBreaker from '@keymanapp/models-wordbreakers';
import {decorateWithJoin} from '../src/join-word-breaker-decorator.js';
describe('The join word breaker decorator', function () {

View file

@ -1,5 +1,5 @@
import { assert } from "chai";
import defaultWordBreaker from './wordbreakers/default-wordbreaker-esm.js';
import defaultWordBreaker from '@keymanapp/models-wordbreakers';
import {decorateWithScriptOverrides} from '../src/script-overrides-decorator.js';
const THIN_SPACE = "\u2009";

View file

@ -6,7 +6,6 @@
"rootDirs": ["./", "../src/"],
"outDir": "../build/test",
"esModuleInterop": true,
"moduleResolution": "node16",
"allowSyntheticDefaultImports": true,
"baseUrl": ".",
"paths": {

View file

@ -1,3 +0,0 @@
Wordbreakers ES Module format
TODO: once we move common/models/wordbreakers to ESM, eliminate this.

File diff suppressed because it is too large Load diff

View file

@ -1,383 +0,0 @@
// TEMP: esm version of /common/models/wordbreakers/default/index.ts
import { I, WORD_BREAK_PROPERTY, WordBreakProperty } from './data.js';
/**
* Word breaker based on Unicode Standard Annex #29, Section 4.1:
* Default Word Boundary Specification.
*
* @see http://unicode.org/reports/tr29/#Word_Boundaries
* @see https://github.com/eddieantonio/unicode-default-word-boundary/tree/v12.0.0
*/
export default function default_(text: string): Span[] {
let boundaries = findBoundaries(text);
if (boundaries.length == 0) {
return [];
}
// All non-empty strings have at least TWO boundaries: at the start and at the end of
// the string.
let spans = [];
for (let i = 0; i < boundaries.length - 1; i++) {
let start = boundaries[i];
let end = boundaries[i + 1];
let span = new LazySpan(text, start, end);
if (isNonSpace(span.text)) {
spans.push(span);
// Preserve a sequence-final space if it exists. Needed to signal "end of word".
} else if (i == boundaries.length - 2) { // if "we just checked the final boundary"...
// We don't want to return the whitespace itself; the correct token is simply ''.
span = new LazySpan(text, end, end);
spans.push(span);
}
}
return spans;
}
// Utilities //
// type WordBreakProperty = data.WordBreakProperty;
// const WordBreakProperty = data.WordBreakProperty;
// type I = data.I;
// const I = data.I;
// const WORD_BREAK_PROPERTY = data.WORD_BREAK_PROPERTY;
/**
* A span that does not cut out the substring until it absolutely has to!
*/
class LazySpan implements Span {
private _source: string;
readonly start: number;
readonly end: number;
constructor(source: string, start: number, end: number) {
this._source = source;
this.start = start;
this.end = end;
}
get text(): string {
return this._source.substring(this.start, this.end);
}
get length(): number {
return this.end - this.start;
}
}
/**
* Returns true when the chunk does not solely consist of whitespace.
*
* @param chunk a chunk of text. Starts and ends at word boundaries.
*/
function isNonSpace(chunk: string): boolean {
return !Array.from(chunk).map(property).every(wb => (
wb === WordBreakProperty.CR ||
wb === WordBreakProperty.LF ||
wb === WordBreakProperty.Newline ||
wb === WordBreakProperty.WSegSpace
));
}
/**
* Yields a series of string indices where a word break should
* occur. That is, there should be a break BEFORE each string
* index yielded by this generator.
*
* @param text Text to find word boundaries in.
*/
function findBoundaries(text: string): number[] {
// WB1 and WB2: no boundaries if given an empty string.
if (text.length === 0) {
// There are no boundaries in an empty string!
return [];
}
// This algorithm works by maintaining a sliding window of four SCALAR VALUES.
//
// - Scalar values? JavaScript strings are NOT actually a string of
// Unicode code points; some characters are made up of TWO
// JavaScript indices. e.g.,
// "💩".length === 2;
// "💩"[0] === '\uD83D';
// "💩"[1] === '\uDCA9';
//
// These characters that are represented by TWO indices are
// called "surrogate pairs". Since we don't want to be in the
// "middle" of a character, make sure we're always advancing
// by scalar values, and NOT indices. That means, we sometimes
// need to advance by TWO indices, not just one.
// - Four values? Some rules look at what's to the left of
// left, and some look at what's to the right of right. So
// keep track of this!
let boundaries = [];
let rightPos: number;
let lookaheadPos = 0; // lookahead, one scalar value to the right of right.
// Before the start of the string is also the start of the string.
let lookbehind: WordBreakProperty;
let left = WordBreakProperty.sot;
let right = WordBreakProperty.sot;
let lookahead = wordbreakPropertyAt(0);
// Count RIs to make sure we're not splitting emoji flags:
let nConsecutiveRegionalIndicators = 0;
do {
// Shift all positions, one scalar value to the right.
rightPos = lookaheadPos;
lookaheadPos = positionAfter(lookaheadPos);
// Shift all properties, one scalar value to the right.
[lookbehind, left, right, lookahead] =
[left, right, lookahead, wordbreakPropertyAt(lookaheadPos)];
// Break at the start and end of text, unless the text is empty.
// WB1: Break at start of text...
if (left === WordBreakProperty.sot) {
boundaries.push(rightPos);
continue;
}
// WB2: Break at the end of text...
if (right === WordBreakProperty.eot) {
boundaries.push(rightPos);
break; // Reached the end of the string. We're done!
}
// WB3: Do not break within CRLF:
if (left === WordBreakProperty.CR && right === WordBreakProperty.LF)
continue;
// WB3b: Otherwise, break after...
if (left === WordBreakProperty.Newline ||
left === WordBreakProperty.CR ||
left === WordBreakProperty.LF) {
boundaries.push(rightPos);
continue;
}
// WB3a: ...and before newlines
if (right === WordBreakProperty.Newline ||
right === WordBreakProperty.CR ||
right === WordBreakProperty.LF) {
boundaries.push(rightPos);
continue;
}
// TODO: WB3c is not implemented, due to its complex, error-prone
// implementation, requiring a ginormous regexp, and the fact that
// the only thing it does is prevent big emoji sequences from being
// split up, like 🧚🏼‍♂️
// https://www.unicode.org/Public/emoji/12.0/emoji-zwj-sequences.txt
// WB3d: Keep horizontal whitespace together
if (left === WordBreakProperty.WSegSpace && right == WordBreakProperty.WSegSpace)
continue;
// WB4: Ignore format and extend characters
// This is to keep grapheme clusters together!
// See: Section 6.2: https://unicode.org/reports/tr29/#Grapheme_Cluster_and_Format_Rules
// N.B.: The rule about "except after sot, CR, LF, and
// Newline" already been by WB1, WB2, WB3a, and WB3b above.
while (right === WordBreakProperty.Format ||
right === WordBreakProperty.Extend ||
right === WordBreakProperty.ZWJ) {
// Continue advancing in the string, as if these
// characters do not exist. DO NOT update left and
// lookbehind however!
[rightPos, lookaheadPos] = [lookaheadPos, positionAfter(lookaheadPos)];
[right, lookahead] = [lookahead, wordbreakPropertyAt(lookaheadPos)];
}
// In ignoring the characters in the previous loop, we could
// have fallen off the end of the string, so end the loop
// prematurely if that happens!
if (right === WordBreakProperty.eot) {
boundaries.push(rightPos);
break;
}
// WB4 (continued): Lookahead must ALSO ignore these format,
// extend, ZWJ characters!
while (lookahead === WordBreakProperty.Format ||
lookahead === WordBreakProperty.Extend ||
lookahead === WordBreakProperty.ZWJ) {
// Continue advancing in the string, as if these
// characters do not exist. DO NOT update left and right,
// however!
lookaheadPos = positionAfter(lookaheadPos);
lookahead = wordbreakPropertyAt(lookaheadPos);
}
// WB5: Do not break between most letters.
if (isAHLetter(left) && isAHLetter(right))
continue;
// Do not break across certain punctuation
// WB6: (Don't break before apostrophes in contractions)
if (isAHLetter(left) && isAHLetter(lookahead) &&
(right === WordBreakProperty.MidLetter || isMidNumLetQ(right)))
continue;
// WB7: (Don't break after apostrophes in contractions)
if (isAHLetter(lookbehind) && isAHLetter(right) &&
(left === WordBreakProperty.MidLetter || isMidNumLetQ(left)))
continue;
// WB7a
if (left === WordBreakProperty.Hebrew_Letter && right === WordBreakProperty.Single_Quote)
continue;
// WB7b
if (left === WordBreakProperty.Hebrew_Letter && right === WordBreakProperty.Double_Quote &&
lookahead === WordBreakProperty.Hebrew_Letter)
continue;
// WB7c
if (lookbehind === WordBreakProperty.Hebrew_Letter && left === WordBreakProperty.Double_Quote &&
right === WordBreakProperty.Hebrew_Letter)
continue;
// Do not break within sequences of digits, or digits adjacent to letters.
// e.g., "3a" or "A3"
// WB8
if (left === WordBreakProperty.Numeric && right === WordBreakProperty.Numeric)
continue;
// WB9
if (isAHLetter(left) && right === WordBreakProperty.Numeric)
continue;
// WB10
if (left === WordBreakProperty.Numeric && isAHLetter(right))
continue;
// Do not break within sequences, such as 3.2, 3,456.789
// WB11
if (lookbehind === WordBreakProperty.Numeric && right === WordBreakProperty.Numeric &&
(left === WordBreakProperty.MidNum || isMidNumLetQ(left)))
continue;
// WB12
if (left === WordBreakProperty.Numeric && lookahead === WordBreakProperty.Numeric &&
(right === WordBreakProperty.MidNum || isMidNumLetQ(right)))
continue;
// WB13: Do not break between Katakana
if (left === WordBreakProperty.Katakana && right === WordBreakProperty.Katakana)
continue;
// Do not break from extenders (e.g., U+202F NARROW NO-BREAK SPACE)
// WB13a
if ((isAHLetter(left) ||
left === WordBreakProperty.Numeric ||
left === WordBreakProperty.Katakana ||
left === WordBreakProperty.ExtendNumLet) &&
right === WordBreakProperty.ExtendNumLet)
continue;
// WB13b
if ((isAHLetter(right) ||
right === WordBreakProperty.Numeric ||
right === WordBreakProperty.Katakana) && left === WordBreakProperty.ExtendNumLet)
continue;
// WB15 & WB16:
// Do not break within emoji flag sequences. That is, do not break between
// regional indicator (RI) symbols if there is an odd number of RI
// characters before the break point.
if (right === WordBreakProperty.Regional_Indicator) {
// Emoji flags are actually composed of TWO scalar values, each being a
// "regional indicator". These indicators correspond to Latin letters. Put
// two of them together, and they spell out an ISO 3166-1-alpha-2 country
// code. Since these always come in pairs, NEVER split the pairs! So, if
// we happen to be inside the middle of an odd numbered of
// Regional_Indicators, DON'T SPLIT IT!
nConsecutiveRegionalIndicators += 1;
if ((nConsecutiveRegionalIndicators % 2) == 1) {
continue;
}
} else {
nConsecutiveRegionalIndicators = 0;
}
// WB999: Otherwise, break EVERYWHERE (including around ideographs)
boundaries.push(rightPos);
} while (rightPos < text.length);
return boundaries;
///// Internal utility functions /////
/**
* Returns the position of the start of the next scalar value. This jumps
* over surrogate pairs.
*
* If asked for the character AFTER the end of the string, this always
* returns the length of the string.
*/
function positionAfter(pos: number): number {
if (pos >= text.length) {
return text.length;
} else if (isStartOfSurrogatePair(text[pos])) {
return pos + 2;
}
return pos + 1;
}
/**
* Return the value of the Word_Break property at the given string index.
* @param pos position in the text.
*/
function wordbreakPropertyAt(pos: number) {
if (pos < 0) {
return WordBreakProperty.sot; // Always "start of string" before the string starts!
} else if (pos >= text.length) {
return WordBreakProperty.eot; // Always "end of string" after the string ends!
} else if (isStartOfSurrogatePair(text[pos])) {
// Surrogate pairs the next TWO items from the string!
return property(text[pos] + text[pos + 1]);
}
return property(text[pos]);
}
// Word_Break rule macros
// See: https://unicode.org/reports/tr29/#WB_Rule_Macros
function isAHLetter(prop: WordBreakProperty): boolean {
return prop === WordBreakProperty.ALetter ||
prop === WordBreakProperty.Hebrew_Letter;
}
function isMidNumLetQ(prop: WordBreakProperty): boolean {
return prop === WordBreakProperty.MidNumLet ||
prop === WordBreakProperty.Single_Quote;
}
}
function isStartOfSurrogatePair(character: string) {
let codeUnit = character.charCodeAt(0);
return codeUnit >= 0xD800 && codeUnit <= 0xDBFF;
}
/**
* Return the Word_Break property value for a character.
* Note that
* @param character a scalar value
*/
function property(character: string): WordBreakProperty {
// This MUST be a scalar value.
// TODO: remove dependence on character.codepointAt()?
let codepoint = character.codePointAt(0) as number;
return searchForProperty(codepoint, 0, WORD_BREAK_PROPERTY.length - 1);
}
/**
* Binary search for the word break property of a given CODE POINT.
*
* The auto-generated data.ts master array defines a **character range**
* lookup table. If a character's codepoint is equal to or greater than
* the I.Start value for an entry and exclusively less than the next entry,
* it falls in the first entry's range bucket and is classified accordingly
* by this method.
*/
function searchForProperty(codePoint: number, left: number, right: number): WordBreakProperty {
// All items that are not found in the array are assigned the 'Other' property.
if (right < left) {
return WordBreakProperty.Other;
}
let midpoint = left + ~~((right - left) / 2);
let candidate = WORD_BREAK_PROPERTY[midpoint];
let nextRange = WORD_BREAK_PROPERTY[midpoint + 1];
let startOfNextRange = nextRange ? nextRange[I.Start] : Infinity;
if (codePoint < candidate[I.Start]) {
return searchForProperty(codePoint, left, midpoint - 1);
} else if (codePoint >= startOfNextRange) {
return searchForProperty(codePoint, midpoint + 1, right);
}
// We found it!
return candidate[I.Value];
}

View file

@ -1,3 +1,3 @@
{
"extends": "../../../tsconfig.esm-base.json",
"extends": "../../../tsconfig.base.json",
}

View file

@ -5,7 +5,7 @@
!include ..\Defines.mak
build: .virtual
$(GIT_BASH_FOR_KEYMAN) build.sh --production --test
$(GIT_BASH_FOR_KEYMAN) build.sh configure build test installer
clean: .virtual
#TODO: move to build.sh `clean` target

View file

@ -11,7 +11,7 @@ isNodeX64() {
# [[ $(file -b "$(which node)" | grep x86-64) ]] && echo 1 || echo 0
}
build_addins() {
do_build_addins() {
local NODEX64=$(isNodeX64)
local ARCH=x64
local TRAYICON_TARGET=addon.x64.node
@ -29,8 +29,13 @@ build_addins() {
echo "TRAYICON_TARGET=$TRAYICON_TARGET"
echo "HIDECONSOLE_TARGET=$HIDECONSOLE_TARGET"
HIDECONSOLE_TARGET="$KEYMAN_ROOT/developer/src/server/src/win32/console/$HIDECONSOLE_TARGET"
TRAYICON_TARGET="$KEYMAN_ROOT/developer/src/server/src/win32/trayicon/$TRAYICON_TARGET"
local HIDECONSOLE_SRC_TARGET="$KEYMAN_ROOT/developer/src/server/src/win32/console/$HIDECONSOLE_TARGET"
local HIDECONSOLE_BIN_TARGET="$KEYMAN_ROOT/developer/src/server/build/src/win32/console/$HIDECONSOLE_TARGET"
local TRAYICON_SRC_TARGET="$KEYMAN_ROOT/developer/src/server/src/win32/trayicon/$TRAYICON_TARGET"
local TRAYICON_BIN_TARGET="$KEYMAN_ROOT/developer/src/server/build/src/win32/trayicon/$TRAYICON_TARGET"
mkdir -p "$(dirname "$HIDECONSOLE_BIN_TARGET")"
mkdir -p "$(dirname "$TRAYICON_BIN_TARGET")"
#
# Build node-windows-trayicon
@ -39,7 +44,8 @@ build_addins() {
pushd "$KEYMAN_ROOT/node_modules/node-windows-trayicon"
rm -rf build
npx node-gyp clean configure build --arch=$ARCH --silent
cp build/Release/addon.node "$TRAYICON_TARGET"
cp build/Release/addon.node "$TRAYICON_SRC_TARGET"
cp build/Release/addon.node "$TRAYICON_BIN_TARGET"
popd
#
@ -49,7 +55,8 @@ build_addins() {
pushd "$KEYMAN_ROOT/node_modules/hetrodo-node-hide-console-window-napi"
rm -rf build
npx node-gyp clean configure build --arch=$ARCH --silent
cp build/Release/node-hide-console-window.node "$HIDECONSOLE_TARGET"
cp build/Release/node-hide-console-window.node "$HIDECONSOLE_SRC_TARGET"
cp build/Release/node-hide-console-window.node "$HIDECONSOLE_BIN_TARGET"
popd
#
@ -57,10 +64,10 @@ build_addins() {
#
if (( NODEX64 )); then
[[ $(isFileX64 "$TRAYICON_TARGET") == 1 ]] || builder_die "$TRAYICON_TARGET should be 64-bit"
[[ $(isFileX64 "$HIDECONSOLE_TARGET") == 1 ]] || builder_die "$HIDECONSOLE_TARGET should be 64-bit"
[[ $(isFileX64 "$TRAYICON_BIN_TARGET") == 1 ]] || builder_die "$TRAYICON_TARGET should be 64-bit"
[[ $(isFileX64 "$HIDECONSOLE_BIN_TARGET") == 1 ]] || builder_die "$HIDECONSOLE_TARGET should be 64-bit"
else
[[ $(isFileX64 "$TRAYICON_TARGET") == 0 ]] || builder_die "$TRAYICON_TARGET should not be 64-bit"
[[ $(isFileX64 "$HIDECONSOLE_TARGET") == 0 ]] || builder_die "$HIDECONSOLE_TARGET should not be 64-bit"
[[ $(isFileX64 "$TRAYICON_BIN_TARGET") == 0 ]] || builder_die "$TRAYICON_TARGET should not be 64-bit"
[[ $(isFileX64 "$HIDECONSOLE_BIN_TARGET") == 0 ]] || builder_die "$HIDECONSOLE_TARGET should not be 64-bit"
fi
}

View file

@ -1,10 +1,4 @@
#!/usr/bin/env bash
#
# Compiles Keyman Developer Server for deployment
#
# Exit on command failure and when using unset variables:
set -eu
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
@ -16,121 +10,68 @@ EX_USAGE=64
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
. "$KEYMAN_ROOT/resources/build/jq.inc.sh"
pushd "$(dirname "$THIS_SCRIPT")"
cd "$THIS_SCRIPT_PATH"
# Build the main script.
build () {
npm run build || builder_die "Could not build top-level JavaScript file."
builder_describe "Build Keyman Developer Server" \
@/common/web/keyman-version \
@/web \
clean \
configure \
build \
test \
"installer Prepare for Keyman Developer installer" \
"publish Publish to NPM" \
":server Keyman Developer Server main program" \
":addins Windows addins for GUI integration"
builder_describe_internal_dependency \
publish:server build:server \
publish:server build:addins
builder_describe_outputs \
configure:server /node_modules \
configure:addins /node_modules \
build:server /developer/src/server/build/src/index.js \
build:addins /developer/src/server/build/src/win32/trayicon/addon.node
builder_parse "$@"
#-------------------------------------------------------------------------------------------------------------------
function clean_server() {
rm -rf "$THIS_SCRIPT_PATH/build"
rm -rf "$THIS_SCRIPT_PATH/node_modules"
rm -rf "$THIS_SCRIPT_PATH/tsconfig.tsbuildinfo"
rm -rf "$THIS_SCRIPT_PATH/src/site/resource"
# No longer in use, cleanup from previous versions:
rm -rf "$THIS_SCRIPT_PATH/dist"
}
display_usage ( ) {
echo "Usage: $0 [--production|--watch] [--test|--tdd]"
echo " $0 --help"
echo
echo " --help displays this screen and exits"
echo " --production, -p builds production release in /developer/bin/server/"
echo " --skip-package-install, -S don't run npm install (not valid with --production)"
echo " --test, -t runs unit tests after building"
#echo " --watch, -w builds dev server in watch mode"
echo " --tdd runs unit tests WITHOUT building"
echo " --no-build-addins don't build/copy Win32 addins"
echo " --no-build-kmw don't build KeymanWeb"
echo " --no-copy-kmw don't copy KeymanWeb"
}
################################ Main script ################################
run_tests=0
production=0
build=1
install_dependencies=1
build_keymanweb=1
copy_keymanweb=1
build_addins=1
# Process command-line arguments
while [[ $# -gt 0 ]] ; do
key="$1"
case $key in
--help|-h|-?)
display_usage
exit
;;
--production|-p)
production=1
;;
--skip-package-install|-S)
install_dependencies=0
;;
--no-build-kmw)
build_keymanweb=0
;;
--no-build-addins)
build_addins=0
;;
--no-copy-kmw)
copy_keymanweb=0
;;
--test)
run_tests=1
;;
--tdd)
run_tests=1
build=0
install_dependencies=0
;;
*)
echo "$0: invalid option: $key"
display_usage
exit $EX_USAGE
esac
shift # past the processed argument
done
# ----------------------------------------
# Install dependencies
# ----------------------------------------
# Check if Node.JS/npm is installed.
type npm >/dev/null ||\
builder_die "Build environment setup error detected! Please ensure Node.js is installed!"
if (( install_dependencies )) ; then
function configure_server() {
verify_npm_setup
# See https://github.com/bubenshchykov/ngrok/issues/254, https://github.com/bubenshchykov/ngrok/pull/255
# TODO: this is horrible; is there a way we can avoid this?
rm -f "$KEYMAN_ROOT"/node_modules/ngrok/bin/ngrok.exe
fi
}
# ----------------------------------------
# Rebuild and bundle addins
# ----------------------------------------
if (( build_addins )); then
. ./build-addins.inc.sh
function build_addins() {
# Rebuild and bundle addins
source ./build-addins.inc.sh
# If we have an x64 version of node installed
if [[ $(isNodeX64) ]]; then
build_addins
do_build_addins
fi
# Build with the Keyman Developer x86 version of node
PATH="$KEYMAN_ROOT/developer/src/inst/node/dist:$PATH" build_addins
fi
PATH="$KEYMAN_ROOT/developer/src/inst/node/dist:$PATH" do_build_addins
}
# ----------------------------------------
# Build and bundle KeymanWeb
# ----------------------------------------
if (( build_keymanweb )); then
pushd "$KEYMAN_ROOT/web/"
./build.sh build --debug
popd
fi
if (( copy_keymanweb )); then
WEB_SRC="$KEYMAN_ROOT/web/build/publish/debug"
DST="$(dirname "$THIS_SCRIPT")/src/site/resource"
function build_server() {
# Copy keymanweb build artifacts
local WEB_SRC="$KEYMAN_ROOT/web/build/publish/debug"
local DST="$THIS_SCRIPT_PATH/src/site/resource"
rm -rf "$DST"
mkdir -p "$DST/osk"
@ -140,33 +81,26 @@ if (( copy_keymanweb )); then
cp -R "$WEB_SRC/ui/"* "$DST/ui/"
cp "$KEYMAN_ROOT/web/LICENSE" "$DST/"
cp "$KEYMAN_ROOT/web/README.md" "$DST/"
fi
# ----------------------------------------
# Build the project
# ----------------------------------------
# Build server
tsc --build
npm run build || builder_die "Compilation failed."
echo "Typescript compilation successful."
# Post build
mkdir -p "$THIS_SCRIPT_PATH/build/src/site/"
mkdir -p "$THIS_SCRIPT_PATH/build/src/win32/"
cp -r "$THIS_SCRIPT_PATH/src/site/"** "$THIS_SCRIPT_PATH/build/src/site/"
cp -r "$THIS_SCRIPT_PATH/src/win32/"** "$THIS_SCRIPT_PATH/build/src/win32/"
# ----------------------------------------
# Unit tests
# ----------------------------------------
replaceVersionStrings "$THIS_SCRIPT_PATH/build/src/site/lib/sentry/init.js.in" "$THIS_SCRIPT_PATH/build/src/site/lib/sentry/init.js"
rm "$THIS_SCRIPT_PATH/build/src/site/lib/sentry/init.js.in"
}
if (( run_tests )); then
npm test || builder_die "Tests failed"
fi
# ----------------------------------------
# Deploy to dist/
# ----------------------------------------
if (( production )) ; then
function installer_server() {
# We need to build in a tmp folder so that npm doesn't get confused by our
# monorepo setup, and so we can copy the relevant node_modules in, because
# we'll need them in order to build the deployable version.
PRODBUILDTEMP=`mktemp -d`
local PRODBUILDTEMP=`mktemp -d`
echo "Preparing in $PRODBUILDTEMP"
# Remove @keymanapp devDependencies because they won't install outside the
# monorepo context
@ -180,14 +114,35 @@ if (( production )) ; then
rm -f node_modules/ngrok/bin/ngrok.exe
popd
# @keymanapp/keyman-version is required in dist now but we need to copy it in manually
# @keymanapp/keyman-version is required in build/ now but we need to copy it in manually
mkdir -p "$PRODBUILDTEMP/node_modules/@keymanapp/"
cp -R "$KEYMAN_ROOT/node_modules/@keymanapp/keyman-version/" "$PRODBUILDTEMP/node_modules/@keymanapp/"
# We'll build in the $KEYMAN_ROOT/developer/bin/server/ folder
rm -rf "$KEYMAN_ROOT/developer/bin/server/"
mkdir -p "$KEYMAN_ROOT/developer/bin/server/dist/"
cp -R dist/* "$KEYMAN_ROOT/developer/bin/server/dist/"
mkdir -p "$KEYMAN_ROOT/developer/bin/server/build/"
cp -R build/* "$KEYMAN_ROOT/developer/bin/server/build/"
cp -R "$PRODBUILDTEMP"/* "$KEYMAN_ROOT/developer/bin/server/"
rm -rf "$PRODBUILDTEMP"
fi
}
function test_server() {
# eslint .
tsc --build test
# c8 --reporter=lcov --reporter=text
mocha
}
builder_run_action clean:server clean_server
builder_run_action configure:server configure_server
builder_run_action build:server build_server
builder_run_action build:addins build_addins
builder_run_action test:server test_server
# builder_run_action test:addins # no op
builder_run_action installer:server installer_server
# TODO: consider 'watch'
# function watch_server() {
# tsc-watch --onSuccess "node --inspect ." --onFailure "node --inspect ."
# }
# builder_run_action watch:server watch_server

View file

@ -1,13 +1,11 @@
{
"name": "@keymanapp/developer-server",
"description": "Keyman Developer backend server",
"main": "dist/index.js",
"main": "build/src/index.js",
"type": "module",
"scripts": {
"build": "tsc -b",
"postbuild": "npx gosh ./postbuild.sh",
"prod": "node .",
"test": "mocha",
"watch": "npm run postbuild && tsc-watch --onSuccess \"node --inspect .\" --onFailure \"node --inspect .\""
"build": "npx gosh ./build.sh build",
"test": "npx gosh ./build.sh test"
},
"license": "MIT",
"dependencies": {
@ -24,13 +22,13 @@
"node-windows-trayicon": "keymanapp/node-windows-trayicon#keyman-16.0"
},
"devDependencies": {
"@keymanapp/resources-gosh": "*",
"@keymanapp/keyman-version": "*",
"@keymanapp/resources-gosh": "*",
"@types/chai": "^4.3.0",
"@types/express": "^4.17.13",
"@types/mocha": "^9.1.0",
"@types/multer": "^1.4.7",
"@types/node": "^17.0.0",
"@types/node": "^20.4.1",
"@types/ws": "^8.2.2",
"chai": "^4.3.4",
"copyfiles": "^2.4.1",
@ -41,6 +39,6 @@
},
"mocha": {
"require": "ts-node/register",
"spec": "**/*.test.ts"
"spec": "build/**/*.test.js"
}
}

View file

@ -1,25 +0,0 @@
#!/usr/bin/env bash
#
# postbuild script run by npm during/after a build
#
# Exit on command failure and when using unset variables:
set -eu
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
. "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh"
## END STANDARD BUILD SCRIPT INCLUDE
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
LOCAL_ROOT="$(dirname "$THIS_SCRIPT")"
mkdir -p "$LOCAL_ROOT/dist/site/"
mkdir -p "$LOCAL_ROOT/dist/win32/"
cp -r "$LOCAL_ROOT/src/site/"** "$LOCAL_ROOT/dist/site/"
cp -r "$LOCAL_ROOT/src/win32/"** "$LOCAL_ROOT/dist/win32/"
replaceVersionStrings "$LOCAL_ROOT/dist/site/lib/sentry/init.js.in" "$LOCAL_ROOT/dist/site/lib/sentry/init.js"
rm "$LOCAL_ROOT/dist/site/lib/sentry/init.js.in"

View file

@ -1,4 +1,4 @@
import fs = require('fs');
import * as fs from 'fs';
export class Configuration {
public readonly appDataPath: string;

View file

@ -1,5 +1,5 @@
import fs = require('fs');
import { configuration } from './config';
import * as fs from 'fs';
import { configuration } from './config.js';
export interface DebugObject {
id: string;

View file

@ -1,5 +1,5 @@
import { extractVersionData } from './version-data';
import { extractVersionData } from './version-data.js';
// TODO: environment should be just KEYMAN_VERSION
const KEYMAN_VERSION = require("@keymanapp/keyman-version").KEYMAN_VERSION;
import KEYMAN_VERSION from "@keymanapp/keyman-version";
export const environment = extractVersionData(KEYMAN_VERSION.VERSION_WITH_TAG);

View file

@ -1,6 +1,6 @@
import chalk = require('chalk');
import express = require('express');
import { DebugObject, isValidId, simplifyId } from "../../../data";
import * as express from 'express';
import chalk from 'chalk';
import { DebugObject, isValidId, simplifyId } from "../../../data.js";
export default function apiGet (data: { [id: string]: DebugObject }, req: express.Request, res: express.Response, next: express.NextFunction) {
let id = req.query['id'] as string;

View file

@ -1,9 +1,9 @@
import express = require('express');
import { DebugObject, isValidId, simplifyId } from "../../../data";
import fs = require('fs');
import crypto = require('crypto');
import { configuration } from '../../../config';
import chalk = require('chalk');
import * as express from 'express';
import { DebugObject, isValidId, simplifyId } from "../../../data.js";
import * as fs from 'fs';
import * as crypto from 'crypto';
import { configuration } from '../../../config.js';
import chalk from 'chalk';
// We allow only 12 objects of each type in the cache
const MAX_OBJECTS = 12;

View file

@ -1,7 +1,7 @@
import express = require('express');
import { DebugObject, isValidId, simplifyId } from "../../../data";
import fs = require('fs');
import chalk = require('chalk');
import * as express from 'express';
import { DebugObject, isValidId, simplifyId } from "../../../data.js";
import * as fs from 'fs';
import chalk from 'chalk';
export default function apiUnregister<O extends DebugObject> (root:{ [id: string]: O }, req: express.Request, res: express.Response, next: express.NextFunction) {
let id = req.body['id'];

View file

@ -1,6 +1,6 @@
import chalk = require('chalk');
import express = require('express');
import { data, DebugFont, simplifyId } from "../../../data";
import chalk from 'chalk';
import * as express from 'express';
import { data, DebugFont, simplifyId } from "../../../data.js";
export default function apiKeyboardRegister (req: express.Request, res: express.Response, next: express.NextFunction) {
const id = simplifyId(req.body['id']);

View file

@ -1,6 +1,6 @@
import chalk = require('chalk');
import express = require('express');
import { data, DebugKeyboard } from "../../../data";
import chalk from 'chalk';
import * as express from 'express';
import { data, DebugKeyboard } from "../../../data.js";
export default function apiKeyboardRegister (req: express.Request, res: express.Response, next: express.NextFunction) {
const keyboard: DebugKeyboard = data.keyboards[req.body['id']];

View file

@ -1,6 +1,6 @@
import chalk = require('chalk');
import express = require('express');
import { data, DebugPackage } from "../../../data";
import chalk from 'chalk';
import * as express from 'express';
import { data, DebugPackage } from "../../../data.js";
export default function apiPackageRegister (req: express.Request, res: express.Response, next: express.NextFunction) {
const kmp: DebugPackage = data.packages[req.body['id']];

View file

@ -1,6 +1,6 @@
import express = require('express');
import path = require('path');
import { data, SiteData } from "../../data";
import * as express from 'express';
import * as path from 'path';
import { data, SiteData } from "../../data.js";
export default function handleIncKeyboardsCss (req: express.Request, res: express.Response) {
let headers = {"Content-Type": "text/css"};

View file

@ -1,5 +1,5 @@
import express = require('express');
import { SiteData, data } from "../../data";
import * as express from 'express';
import { SiteData, data } from "../../data.js";
export default function handleIncKeyboardsJs (req: express.Request, res: express.Response) {
let headers = {"Content-Type": "application/javascript"};

View file

@ -1,6 +1,6 @@
import express = require('express');
import { data } from "../../data";
import { environment } from '../../environment';
import * as express from 'express';
import { data } from "../../data.js";
import { environment } from '../../environment.js';
export default function handleIncPackagesJson (req: express.Request, res: express.Response) {
const packages = Object.keys(data.packages).map(id => { return { id: id, filename: id+'.kmp', name: data.packages[id].name} });

View file

@ -1,21 +1,21 @@
import { environment } from './environment';
import { environment } from './environment.js';
const Sentry = require("@sentry/node");
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: 'https://39b25a09410349a58fe12aaf721565af@o1005580.ingest.sentry.io/5983519', // Keyman Developer
environment: environment.versionEnvironment,
release: environment.versionGitTag
});
import express = require('express');
import ws = require('ws');
import os = require('os');
import multer = require('multer');
import fs = require('fs');
import setupRoutes from './routes';
import { configuration } from './config';
import tray from './tray';
import chalk = require('chalk');
import express from 'express';
import * as ws from 'ws';
import * as os from 'os';
import multer from 'multer';
import * as fs from 'fs';
import setupRoutes from './routes.js';
import { configuration } from './config.js';
import tray from './tray.js';
import chalk from 'chalk';
const options = {
ngrokLog: false, // Set this to true if you need to see ngrok logs in the console
@ -58,7 +58,7 @@ const upload = multer({ storage: multer.memoryStorage(), limits: { fileSize: 102
/* Websockets */
const wsServer = new ws.Server({ noServer: true });
const wsServer = new ws.WebSocketServer({ noServer: true });
wsServer.on('connection', socket => {
socket.on('message', (message) => {
console.debug('wsServer.socket.onmessage: '+message.toString());
@ -87,7 +87,7 @@ server.on('upgrade', (request, socket, head) => {
configuration.ngrokEndpoint = '';
if(configuration.useNgrok && os.platform() == 'win32' && fs.existsSync(configuration.ngrokBinPath)) {
const ngrok = require('ngrok');
const ngrok: any = await import('ngrok');
(async function() {
configuration.ngrokEndpoint = await ngrok.connect({
proto: 'http',

1
developer/src/server/src/ngrok.d.ts vendored Normal file
View file

@ -0,0 +1 @@
declare module 'ngrok';

View file

@ -1,21 +1,21 @@
import express = require('express');
import multer = require('multer');
import ws = require('ws');
import handleIncKeyboardsJs from './handlers/inc/keyboards-js';
import { data, DebugFont, DebugKeyboard, DebugModel, DebugObject, DebugPackage, isValidId } from './data';
import apiGet from './handlers/api/debugobject/get';
import apiRegister, { apiRegisterFile } from './handlers/api/debugobject/register';
import apiKeyboardRegister from './handlers/api/keyboard/register';
import apiFontRegister from './handlers/api/font/register';
import apiUnregister from './handlers/api/debugobject/unregister';
import handleIncPackagesJson from './handlers/inc/packages-json';
import apiPackageRegister from './handlers/api/package/register';
import handleIncKeyboardsCss from './handlers/inc/keyboards-css';
import { Environment } from './version-data';
import { configuration } from './config';
import chalk = require('chalk');
import * as express from 'express';
import * as ws from 'ws';
import * as multer from 'multer';
import handleIncKeyboardsJs from './handlers/inc/keyboards-js.js';
import { data, DebugFont, DebugKeyboard, DebugModel, DebugObject, DebugPackage, isValidId } from './data.js';
import apiGet from './handlers/api/debugobject/get.js';
import apiRegister, { apiRegisterFile } from './handlers/api/debugobject/register.js';
import apiKeyboardRegister from './handlers/api/keyboard/register.js';
import apiFontRegister from './handlers/api/font/register.js';
import apiUnregister from './handlers/api/debugobject/unregister.js';
import handleIncPackagesJson from './handlers/inc/packages-json.js';
import apiPackageRegister from './handlers/api/package/register.js';
import handleIncKeyboardsCss from './handlers/inc/keyboards-css.js';
import { Environment } from './version-data.js';
import { configuration } from './config.js';
import chalk from 'chalk';
export default function setupRoutes(app: express.Express, upload: multer.Multer, wsServer: ws.Server, environment: Environment ) {
export default function setupRoutes(app: express.Express, upload: multer.Multer, wsServer: ws.WebSocketServer, environment: Environment ) {
/* Middleware - JSON and logging */
@ -49,7 +49,7 @@ export default function setupRoutes(app: express.Express, upload: multer.Multer,
/* All routes */
app.use('/', express.static('dist/site'));
app.use('/', express.static('build/src/site'));
app.post('/upload', localhostOnly, upload.single('file'), (req, res, next) => {
const name = req.file.originalname;
@ -170,7 +170,7 @@ export default function setupRoutes(app: express.Express, upload: multer.Multer,
/* Utility functions */
function notifyClients(wsServer: ws.Server, res: express.Request, req: express.Response, next: express.NextFunction) {
function notifyClients(wsServer: ws.WebSocketServer, res: express.Request, req: express.Response, next: express.NextFunction) {
wsServer.clients.forEach(c => {
c.send('refresh', (err) => {
if(err) console.error(chalk.red('Websocket send error '+err.message));

View file

@ -1,4 +1,4 @@
import os = require('os');
import * as os from 'os';
class TrayStub {
public start(localPort: number, ngrokAddress: string) {}
@ -9,7 +9,7 @@ class TrayStub {
let tray = new TrayStub();
if(os.platform() == 'win32') {
const Win32Tray = require('./win32-tray');
const { Win32Tray } = await import('./win32-tray.js');
tray = new Win32Tray();
}

View file

@ -1,14 +1,15 @@
import path = require("path");
import * as path from "path";
import * as url from 'url';
// TODO: this is a Windows-only tray icon. There are a number of
// cross-platform solutions but none of them are wonderful. We
// should replace this when we find a decent one.
const WindowsTrayicon = require("./win32/trayicon");
const WindowsConsole = require("./win32/console");
const open = require("open");
import WindowsTrayicon from "./win32/trayicon/index.js";
import WindowsConsole from "./win32/console/index.js";
import open from 'open';
module.exports = class Win32Tray {
export class Win32Tray {
private myTrayApp: any;
public restart(localPort: number, ngrokAddress: string) {
@ -55,7 +56,7 @@ module.exports = class Win32Tray {
this.myTrayApp = new WindowsTrayicon({
title: "Keyman Developer Server",
icon: path.resolve(__dirname, "site", "favicon.ico"),
icon: path.resolve(url.fileURLToPath(new URL('.', import.meta.url)), "site", "favicon.ico"),
menu: menu
});

View file

@ -1,5 +0,0 @@
declare module "node-hide-console-window" {
function hideConsole(): void
function showConsole(): void
}

View file

@ -1,7 +0,0 @@
const os = require('os');
const {showConsole, hideConsole} = require(os.arch() == 'ia32' ? "./node-hide-console-window" : "./node-hide-console-window.x64");
module.exports = {
showConsole,
hideConsole
}

View file

@ -0,0 +1,6 @@
import * as os from 'os';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const {showConsole, hideConsole} = require(os.arch() == 'ia32' ? "./node-hide-console-window" : "./node-hide-console-window.x64");
export default { showConsole, hideConsole };

View file

@ -1,8 +1,17 @@
const os = require('os');
import * as os from 'os';
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const { CTrayIconContainer } = require(os.arch() == 'ia32' ? "./addon" : "./addon.x64");
class WindowsTrayicon {
constructor(options) {
__itemCallbacks: any[];
__icon: any;
__trayTitle: any;
__menuItems: any;
__nativeTray: any;
constructor(options: any) {
this.__itemCallbacks = [];
this.__icon = options.icon;
this.__trayTitle = options.title || "";
@ -12,7 +21,7 @@ class WindowsTrayicon {
for (const item of this.__menuItems) {
this.__nativeTray.AddMenuItem(item.id, item.caption);
}
this.__nativeTray.OnMenuItem((id) => {
this.__nativeTray.OnMenuItem((id: any) => {
for (const cb of this.__itemCallbacks) {
cb(id);
}
@ -23,15 +32,15 @@ class WindowsTrayicon {
}
this.__nativeTray.Start();
}
item(cb) {
item(cb: any) {
if ("function" === typeof cb) {
this.__itemCallbacks.push(cb);
}
}
balloon(title, text, timeout = 5000) {
balloon(title: any, text: any, timeout = 5000) {
return new Promise((resolve) => {
this.__nativeTray.ShowBalloon(title, text, timeout, () => {
resolve();
resolve(null);
})
});
}
@ -40,4 +49,4 @@ class WindowsTrayicon {
}
}
module.exports = WindowsTrayicon;
export default WindowsTrayicon;

View file

@ -0,0 +1,16 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"rootDir": ".",
"rootDirs": ["./", "../src/"],
"outDir": "../build/test",
"baseUrl": ".",
},
"include": [
"**/*.test.ts"
],
"references": [
{ "path": "../" },
]
}

View file

@ -1,8 +1,6 @@
import {assert} from 'chai';
import 'mocha';
import { extractVersionData } from './version-data';
import { extractVersionData } from '../src/version-data.js';
describe('extractVersionData', function() {
it('should parse version strings', function() {

View file

@ -1,13 +1,13 @@
{
"extends": "../../../tsconfig-base.json",
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"module": "commonjs",
"target": "es2022",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist/",
"outDir": "build/src/",
"rootDir": "src/",
"baseUrl": ".",
"declaration": true,
"alwaysStrict": true,
"noImplicitThis": true,
@ -16,6 +16,7 @@
"strictBindCallApply": true,
"strictFunctionTypes": true,
"noUnusedLocals": true,
"allowJs": true,
"lib": ["es2022"]
},
"include": [

View file

@ -7,9 +7,9 @@
<key>teamID</key>
<string>3YE4W86L3G</string>
<key>signingCertificate</key>
<string>05473BF50CCD4B78B304656FB4D93FDC7EE7ACD0</string>
<string>BB842A0081298BBA6D034C85451750B08FC9EE8A</string>
<key>installerSigningCertificate</key>
<string>05473BF50CCD4B78B304656FB4D93FDC7EE7ACD0</string>
<string>BB842A0081298BBA6D034C85451750B08FC9EE8A</string>
<key>provisioningProfiles</key>
<dict>
<key>Tavultesoft.Keyman</key>

165
package-lock.json generated
View file

@ -271,16 +271,9 @@
"name": "@keymanapp/keyman-version",
"license": "MIT",
"devDependencies": {
"@types/node": "^20.4.1",
"typescript": "^4.9.5"
}
},
"common/web/keyman-version/node_modules/@types/node": {
"version": "20.4.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.1.tgz",
"integrity": "sha512-JIzsAvJeA/5iY6Y/OxZbv1lUcc8dNSE77lb2gnBH+/PJ3lFR1Ccvgwl5JWnHAkNHcRsT0TbpVOsiMKZ1F/yyJg==",
"dev": true
},
"common/web/lm-message-types": {
"name": "@keymanapp/lm-message-types",
"license": "MIT",
@ -2654,7 +2647,7 @@
"@types/express": "^4.17.13",
"@types/mocha": "^9.1.0",
"@types/multer": "^1.4.7",
"@types/node": "^17.0.0",
"@types/node": "^20.4.1",
"@types/ws": "^8.2.2",
"chai": "^4.3.4",
"copyfiles": "^2.4.1",
@ -2674,9 +2667,10 @@
"license": "MIT"
},
"developer/src/server/node_modules/@types/node": {
"version": "17.0.45",
"dev": true,
"license": "MIT"
"version": "20.8.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.2.tgz",
"integrity": "sha512-Vvycsc9FQdwhxE3y3DzeIxuEJbWGDsnrxvMADzTDF/lcdR9/K+AQIeAghTQsHtotg/q0j3WEOYS/jQgSdWue3w==",
"dev": true
},
"developer/src/server/node_modules/busboy": {
"version": "1.6.0",
@ -3830,6 +3824,21 @@
"@types/node": "*"
}
},
"node_modules/@types/yargs": {
"version": "17.0.26",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.26.tgz",
"integrity": "sha512-Y3vDy2X6zw/ZCumcwLpdhM5L7jmyGpmBCTYMHDLqT2IKVMYRRLdv6ZakA+wxhra6Z/3bwhNbNl9bDGXaFU+6rw==",
"dev": true,
"dependencies": {
"@types/yargs-parser": "*"
}
},
"node_modules/@types/yargs-parser": {
"version": "21.0.1",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.1.tgz",
"integrity": "sha512-axdPBuLuEJt0c4yI5OZssC19K2Mq1uKdrfZBzuxLvaztgqUtFYZUNw7lETExPYJR9jdEoIg4mb7RQKRQzOkeGQ==",
"dev": true
},
"node_modules/@types/yauzl": {
"version": "2.9.2",
"license": "MIT",
@ -4753,6 +4762,7 @@
},
"node_modules/camelcase": {
"version": "5.3.1",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@ -5148,6 +5158,7 @@
},
"node_modules/decamelize": {
"version": "1.2.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@ -5884,7 +5895,6 @@
},
"node_modules/escalade": {
"version": "3.1.1",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@ -9573,6 +9583,7 @@
},
"node_modules/p-try": {
"version": "2.2.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
@ -9603,6 +9614,7 @@
},
"node_modules/path-exists": {
"version": "4.0.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -9930,6 +9942,7 @@
},
"node_modules/require-main-filename": {
"version": "2.0.0",
"dev": true,
"license": "ISC"
},
"node_modules/requirejs": {
@ -10170,6 +10183,7 @@
},
"node_modules/set-blocking": {
"version": "2.0.0",
"devOptional": true,
"license": "ISC"
},
"node_modules/set-immediate-shim": {
@ -11172,6 +11186,7 @@
},
"node_modules/which-module": {
"version": "2.0.0",
"dev": true,
"license": "ISC"
},
"node_modules/which-typed-array": {
@ -11231,7 +11246,6 @@
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
@ -11247,7 +11261,6 @@
},
"node_modules/wrap-ansi/node_modules/ansi-regex": {
"version": "5.0.1",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -11255,7 +11268,6 @@
},
"node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8"
@ -11263,7 +11275,6 @@
},
"node_modules/wrap-ansi/node_modules/string-width": {
"version": "4.2.2",
"dev": true,
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
@ -11276,7 +11287,6 @@
},
"node_modules/wrap-ansi/node_modules/strip-ansi": {
"version": "6.0.0",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.0"
@ -11337,7 +11347,6 @@
},
"node_modules/y18n": {
"version": "5.0.8",
"dev": true,
"license": "ISC",
"engines": {
"node": ">=10"
@ -11497,16 +11506,14 @@
"@actions/core": "^1.9.1",
"@actions/github": "^2.1.0",
"typescript": "^4.9.5",
"yargs": "^15.1.0"
"yargs": "^17.7.2"
},
"devDependencies": {
"@types/node": "^13.7.0",
"@types/semver": "^7.1.0",
"@types/yargs": "^17.0.26",
"semver": "^7.5.2",
"ts-node": "^10.9.1"
},
"engines": {
"node": ">=16.0"
}
},
"resources/build/version/node_modules/@types/node": {
@ -11516,74 +11523,37 @@
},
"resources/build/version/node_modules/ansi-regex": {
"version": "5.0.1",
"license": "MIT",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"engines": {
"node": ">=8"
}
},
"resources/build/version/node_modules/cliui": {
"version": "6.0.0",
"license": "ISC",
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
}
},
"resources/build/version/node_modules/find-up": {
"version": "4.1.0",
"license": "MIT",
"dependencies": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
},
"engines": {
"node": ">=8"
"node": ">=12"
}
},
"resources/build/version/node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"resources/build/version/node_modules/locate-path": {
"version": "5.0.0",
"license": "MIT",
"dependencies": {
"p-locate": "^4.1.0"
},
"engines": {
"node": ">=8"
}
},
"resources/build/version/node_modules/p-limit": {
"version": "2.3.0",
"license": "MIT",
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"resources/build/version/node_modules/p-locate": {
"version": "4.1.0",
"license": "MIT",
"dependencies": {
"p-limit": "^2.2.0"
},
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"engines": {
"node": ">=8"
}
},
"resources/build/version/node_modules/string-width": {
"version": "4.2.3",
"license": "MIT",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@ -11595,7 +11565,8 @@
},
"resources/build/version/node_modules/strip-ansi": {
"version": "6.0.1",
"license": "MIT",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dependencies": {
"ansi-regex": "^5.0.1"
},
@ -11603,51 +11574,29 @@
"node": ">=8"
}
},
"resources/build/version/node_modules/wrap-ansi": {
"version": "6.2.0",
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=8"
}
},
"resources/build/version/node_modules/y18n": {
"version": "4.0.3",
"license": "ISC"
},
"resources/build/version/node_modules/yargs": {
"version": "15.4.1",
"license": "MIT",
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dependencies": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^21.1.1"
},
"engines": {
"node": ">=8"
"node": ">=12"
}
},
"resources/build/version/node_modules/yargs-parser": {
"version": "18.1.3",
"license": "ISC",
"dependencies": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
},
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"engines": {
"node": ">=6"
"node": ">=12"
}
},
"resources/gosh": {

View file

@ -88,9 +88,7 @@ echo "increment-version.sh: building resources/build/version"
pushd "$KEYMAN_ROOT"
npm ci
pushd "$KEYMAN_ROOT/resources/build/version"
npm run build:ts
popd
"$KEYMAN_ROOT/resources/build/version/build.sh"
echo "increment-version.sh: running resources/build/version"
pushd "$KEYMAN_ROOT"

View file

@ -47,3 +47,4 @@ coverage
# Build output
dist
lib
build

View file

@ -0,0 +1,24 @@
#!/usr/bin/env bash
## START STANDARD BUILD SCRIPT INCLUDE
# adjust relative paths as necessary
THIS_SCRIPT="$(readlink -f "${BASH_SOURCE[0]}")"
. "${THIS_SCRIPT%/*}/../../../resources/build/build-utils.sh"
## END STANDARD BUILD SCRIPT INCLUDE
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
# This script runs from its own folder
cd "$THIS_SCRIPT_PATH"
################################ Main script ################################
builder_describe "Build version tooling" clean configure build
builder_describe_outputs \
configure /resources/build/version/node_modules \
build /resources/build/version/build/src/index.js
builder_parse "$@"
builder_run_action clean rm -rf build/ node_modules/ dist/ lib/
builder_run_action configure verify_npm_setup
builder_run_action build tsc --build

View file

@ -1,25 +1,24 @@
{
"description": "Automatically updates HISTORY.md based on pull requests",
"type": "module",
"dependencies": {
"@actions/core": "^1.9.1",
"@actions/github": "^2.1.0",
"typescript": "^4.9.5",
"yargs": "^15.1.0"
"yargs": "^17.7.2"
},
"description": "Automatically updates HISTORY.md based on pull requests",
"devDependencies": {
"@types/node": "^13.7.0",
"@types/semver": "^7.1.0",
"@types/yargs": "^17.0.26",
"semver": "^7.5.2",
"ts-node": "^10.9.1"
},
"engines": {
"node": ">=16.0"
},
"files": [
"src"
],
"license": "MIT",
"main": "lib/index.js",
"main": "build/src/index.js",
"name": "@keymanapp/auto-history-action",
"private": true,
"scripts": {

View file

@ -5,7 +5,7 @@ import {
import { GitHub } from '@actions/github';
import { readFileSync, writeFileSync } from 'fs';
import { gt } from 'semver';
import { reportHistory } from './reportHistory';
import { reportHistory } from './reportHistory.js';
interface PRInformation {
title: string;
@ -42,7 +42,8 @@ const splicePullsIntoHistory = async (pulls: PRInformation[]): Promise<{count: n
const versionMatch = new RegExp(`^## ${version} ${tier}`, 'i');
let historyChunks: { heading: string[]; newer: string[]; current: string[]; older: string[] } = {heading:[], newer:[], current:[], older:[]};
let state = "heading";
type ChunkType = keyof typeof historyChunks;
let state: ChunkType = "heading";
for(const line of history) {
if(line.match(versionMatch)) {
// We are in the correct section of history
@ -90,7 +91,7 @@ const splicePullsIntoHistory = async (pulls: PRInformation[]): Promise<{count: n
let found = false;
// Look for the PR in any other chunk -- can be found with merges of master into PR or chained PRs
for(const chunk of ['newer','current','older']) {
for(const chunk of ['newer','current','older'] as ChunkType[]) {
for(const line of historyChunks[chunk]) {
if(line.match(pullNumberRe)) {
found = true;

View file

@ -1,13 +1,14 @@
import { info as logInfo } from '@actions/core';
import { GitHub } from '@actions/github';
import { sendCommentToPullRequestAndRelatedIssues, fixupHistory } from './fixupHistory';
import { incrementVersion } from './incrementVersion';
const yargs = require('yargs');
import { sendCommentToPullRequestAndRelatedIssues, fixupHistory } from './fixupHistory.js';
import { incrementVersion } from './incrementVersion.js';
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { readFileSync } from 'fs';
import { reportHistory } from './reportHistory';
import { reportHistory } from './reportHistory.js';
const argv = yargs
const argv = await yargs(hideBin(process.argv))
.command(['history'], 'Fixes up HISTORY.md with pull request data')
.command(['version'], 'Increments the current patch version in VERSION.md')
.command(['report-history'], 'Print list of outstanding PRs waiting for the next build')
@ -81,10 +82,10 @@ const main = async (): Promise<void> => {
if(argv._.includes('report-history')) {
let pulls = await reportHistory(octokit, argv.base, argv.force, argv['github-pr'], argv.from, argv.to);
let versions = {};
let versions: {[index:string]:any} = {};
pulls.forEach((item) => {
if(typeof item.version == 'string') {
if(typeof versions[item.version] == 'undefined') {
if(typeof (versions)[item.version] == 'undefined') {
versions[item.version] = {data: item.tag_data, pulls: []};
}
// We want to invert the order of the pulls as we go to

View file

@ -2,8 +2,8 @@ import { warning as logWarning, info as logInfo } from '@actions/core';
import { GitHub } from '@actions/github';
import { findLastHistoryPR, getAssociatedPR} from './graphql/queries';
import { spawnChild } from './util/spawnAwait';
import { findLastHistoryPR, getAssociatedPR} from './graphql/queries.js';
import { spawnChild } from './util/spawnAwait.js';
const getPullRequestInformation = async (
octokit: GitHub, base: string
@ -67,7 +67,7 @@ const getAssociatedPRInformation = async (
}
}: any = response;
const node = nodes.find(node => node.state == 'MERGED');
const node = nodes.find((node:any) => node.state == 'MERGED');
return node ? { title: node.title, number: node.number } : undefined;
};

View file

@ -1,7 +1,8 @@
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"rootDir": "."
"rootDir": ".",
"outDir": "build/",
},
"extends": "./tsconfig.production.json",
"include": ["./**/*"]
"include": ["./**/*.ts"]
}

View file

@ -1,25 +0,0 @@
{
"compilerOptions": {
"allowSyntheticDefaultImports": true,
"alwaysStrict": true,
"charset": "utf-8",
"declaration": true,
"declarationMap": true,
"downlevelIteration": true,
"forceConsistentCasingInFileNames": true,
"lib": ["es2017"],
"module": "commonjs",
"noImplicitAny": false,
"noImplicitReturns": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"outDir": "lib",
"pretty": true,
"rootDir": "src",
"sourceMap": true,
"strict": true,
"strictNullChecks": true,
"target": "es2017"
},
"files": ["./src/index.ts"]
}

View file

@ -1,5 +1,18 @@
{
"compilerOptions": {
"module": "ES2022",
"target": "es2022",
"moduleResolution": "node16",
"forceConsistentCasingInFileNames": true,
"sourceMap": true,
"alwaysStrict": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"noImplicitAny": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
"noUnusedLocals": true,
"rootDir": ".",
// TODO: move all compiler options here
@ -9,7 +22,9 @@
"declarationMap": true,
"baseUrl": ".",
"paths": {
"@keymanapp/common-types": ["./common/web/types/src/main"],
"@keymanapp/input-processor": ["./common/web/input-processor/src"],
"@keymanapp/keyboard-processor": ["./common/web/keyboard-processor/src"],
"@keymanapp/keyman": ["./web" ],

View file

@ -1,18 +0,0 @@
{
// Lists only CommonJS or 'none' modules; as we move modules from cjs/none to
// esm, we should move them from here into tsconfig.esm.json. Eventually, when
// we have only ES modules, we'll delete this file.
"files": [],
"include": [],
"references": [
{ "path": "./common/predictive-text/testing/one-stage-embedded-webworker/tsconfig.json" },
{ "path": "./common/predictive-text/testing/two-stage-embedded-webworker/tsconfig.json" },
{ "path": "./common/predictive-text/testing/two-stage-embedded-webworker/worker/tsconfig.json" },
{ "path": "./developer/src/server/tsconfig.json" },
{ "path": "./resources/build/version/tsconfig.json" },
{ "path": "./resources/build/version/tsconfig.production.json" },
// { "path": "./web/bulk_rendering/tsconfig.json" },
]
}

View file

@ -1,24 +0,0 @@
{
"extends": "./tsconfig-base.json",
"compilerOptions": {
"module": "ES2022",
"target": "es2022",
"moduleResolution": "Node16",
"forceConsistentCasingInFileNames": true,
"sourceMap": true,
"alwaysStrict": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"noImplicitAny": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
"noUnusedLocals": true,
"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"],
},
},
}

View file

@ -1,19 +1,28 @@
{
// Lists only ES modules; as we move modules from cjs/none to esm, we should
// move them from tsconfig.cjs.json to here. Eventually, when we have only ES
// modules, we can rename this to tsconfig.json.
"files": [],
"include": [],
"references": [
{ "path": "./core/include/ldml/tsconfig.json" },
//{ "path": "./developer/src/kmc/test/tsconfig.json" },
{ "path": "./common/models/templates/tsconfig.json" },
{ "path": "./common/models/types/tsconfig.json" },
{ "path": "./common/models/wordbreakers/tsconfig.json" },
{ "path": "./common/predictive-text/tsconfig.json" },
{ "path": "./common/tools/hextobin/" },
{ "path": "./common/web/input-processor/tsconfig.json" },
{ "path": "./common/web/keyboard-processor/tsconfig.json" },
{ "path": "./common/web/keyman-version" },
{ "path": "./common/web/lm-message-types/" },
{ "path": "./common/web/lm-worker/" },
{ "path": "./common/web/recorder/tsconfig.json" },
{ "path": "./common/web/sentry-manager/src/tsconfig.json" },
{ "path": "./common/web/types/" },
{ "path": "./common/web/utils/tsconfig.json" },
{ "path": "./developer/src/common/web/test-helpers/tsconfig.json" },
{ "path": "./developer/src/kmc/tsconfig.json" },
// { "path": "./developer/src/kmc-analyze/test/tsconfig.json" },
{ "path": "./developer/src/kmc/test/tsconfig.json" },
{ "path": "./developer/src/kmc-analyze/tsconfig.json" },
// { "path": "./developer/src/kmc-analyze/test/tsconfig.json" },
{ "path": "./developer/src/kmc-kmn/test/tsconfig.json" },
{ "path": "./developer/src/kmc-kmn/tsconfig.json" },
{ "path": "./developer/src/kmc-keyboard-info/test/tsconfig.json" },
@ -26,25 +35,12 @@
{ "path": "./developer/src/kmc-model-info/tsconfig.json" },
{ "path": "./developer/src/kmc-package/test/tsconfig.json" },
{ "path": "./developer/src/kmc-package/tsconfig.json" },
{ "path": "./developer/src/server/tsconfig.json" },
{ "path": "./common/web/keyman-version" },
{ "path": "./common/web/types/" },
{ "path": "./common/web/input-processor/tsconfig.json" },
{ "path": "./common/web/keyboard-processor/tsconfig.json" },
{ "path": "./common/web/recorder/tsconfig.json" },
{ "path": "./common/web/sentry-manager/src/tsconfig.json" },
{ "path": "./common/web/utils/tsconfig.json" },
{ "path": "./common/models/templates/tsconfig.json" },
{ "path": "./common/models/types/tsconfig.json" },
{ "path": "./common/models/wordbreakers/tsconfig.json" },
{ "path": "./common/predictive-text/tsconfig.json" },
{ "path": "./resources/build/version/" },
{ "path": "./web/src/tsconfig.all.json" },
// { "path": "./web/tools/recorder/tsconfig.json" },
// { "path": "./web/tools/sourcemap-root/tsconfig.json" },
{ "path": "./common/web/lm-message-types/" },
{ "path": "./common/web/lm-worker/" },
]
}

View file

@ -1,15 +1,24 @@
{
"extends": "../tsconfig-base.json",
"extends": "../tsconfig.base.json",
// TODO: eliminate settings duplicated in ../tsconfig.base.json
"compilerOptions": {
// Primary settings - the version of ES6 we can target in TS, our downcompile target,
// and our module-related settings.
"allowSyntheticDefaultImports": true,
"lib": ["es6"],
"module": "es6",
"moduleResolution": "Node16",
"target": "es5",
// TODO: These override ../tsconfig.base.json settings, and so should be removed if possible,
// but existing code in web/ breaks some of these settinsg
"noImplicitThis": false,
"noImplicitReturns": false,
"noImplicitAny": false,
"strictFunctionTypes": false,
"noUnusedLocals": false,
// Other settings - declaration files, sourcemapping, and other miscellaneous bits.
"allowJs": false,
"declaration": true,