spiegel-keyman/common/predictive-text/build.sh
2020-01-08 11:53:53 +07:00

182 lines
5.3 KiB
Bash
Executable file

#!/bin/bash
#
# Compiles the Language Modeling Layer for common use in predictive text and autocorrective applications.
# Designed for optimal compatibility with the Keyman Suite.
#
# Exit on command failure and when using unset variables:
set -eu
# Include some helper functions from resources
. ../../resources/shellHelperFunctions.sh
# Exit status on invalid usage.
EX_USAGE=64
LMLAYER_OUTPUT=build
WORKER_OUTPUT=build/intermediate
INCLUDES_OUTPUT=build/includes
NAKED_WORKER=$WORKER_OUTPUT/index.js
EMBEDDED_WORKER=$WORKER_OUTPUT/embedded_worker.js
LEXICAL_MODELS_TYPES=../lexical-model-types
# Build the worker and the main script.
build ( ) {
# Ensure that the build-product destination for any generated include .d.ts files exists.
if ! [ -d $INCLUDES_OUTPUT ]; then
mkdir -p "$INCLUDES_OUTPUT"
fi
# Build worker first; the main file depends on it.
# Then wrap the worker; Then build the main file.
build-worker && wrap-worker && build-main
}
# Builds the top-level JavaScript file (the second stage of compilation)
build-main () {
npm run tsc -- -p ./tsconfig.json || fail "Could not build top-level JavaScript file."
cp ./index.d.ts $INCLUDES_OUTPUT/LMLayer.d.ts
cp ./message.d.ts $INCLUDES_OUTPUT/message.d.ts
}
# Builds the inner JavaScript worker (the first stage of compilation).
# This script must be wrapped.
build-worker () {
if ! [ -d $WORKER_OUTPUT ]; then
mkdir -p "$WORKER_OUTPUT" # Includes any base folders recursively.
fi
npm run tsc -- -p ./worker/tsconfig.json || fail "Could not build worker."
get_builder_OS
# macOS has a slightly different sed, which needs an extension to use for a backup file. Thanks, Apple.
BACKUP_EXT=
if [ $os_id == 'mac' ]; then
BACKUP_EXT='.bak'
fi
# Tweak the output index.d.ts to have an updated reference to message.d.ts
sed -i $BACKUP_EXT 's/path="\.\.\/\.\.\/message\.d\.ts"/path="message\.d\.ts"/g' "${WORKER_OUTPUT}/index.d.ts" \
|| fail "Could not update message.d.ts reference"
mv $WORKER_OUTPUT/index.d.ts $INCLUDES_OUTPUT/LMLayerWorker.d.ts
}
# A nice, extensible method for -clean operations. Add to this as necessary.
clean ( ) {
if [ -d $WORKER_OUTPUT ]; then
rm -rf "$WORKER_OUTPUT" || fail "Failed to erase the prior build."
fi
if [ -d $LMLAYER_OUTPUT ]; then
rm -rf "$LMLAYER_OUTPUT" || fail "Failed to erase the prior build."
fi
}
display_usage ( ) {
echo "Usage: $0 [-clean] [-test | -tdd]"
echo " $0 -help"
echo
echo " -clean to erase pre-existing build products before a re-build"
echo " -help displays this screen and exits"
echo " -tdd skips dependency updates, builds, then runs unit tests only"
echo " -test runs unit and integration tests after building"
}
# Creates embedded_worker.js. Must be run after the worker is built for the
# first time
wrap-worker ( ) {
echo "> wrap-worker-code LMLayerWorkerCode ${NAKED_WORKER} > ${EMBEDDED_WORKER}"
wrap-worker-code LMLayerWorkerCode "${NAKED_WORKER}" > "${EMBEDDED_WORKER}"
}
# Wraps JavaScript code in a way that can be embedded in a worker.
# To get the inner source code, include the file generated by this function,
# then use name.toString() where `name` is the name passed into this
# function.
wrap-worker-code ( ) {
name="$1"
js="$2"
echo "// Autogenerated code. Do not modify!"
printf "function %s () {\n" "${name}"
# Since the worker is compiled with "allowJS=false" so that we can make
# declaration files, we have to insert polyfills here.
# This one's a minimal, targeted polyfill. es6-shim could do the same,
# but also adds a lot more code the worker doesn't need to use.
# Recommended by MDN while keeping the worker lean and efficient.
cat "node_modules/string.prototype.codepointat/codepointat.js"
# Needed to ensure functionality on some older Android devices. (API 19-23 or so)
cat "node_modules/string.prototype.startswith/startswith.js"
# This one's straight from MDN - I didn't find any NPM ones that don't
# use the node `require` statement.
cat "polyfills/array.from.js"
echo ""
cat "${js}"
printf "\n}\n"
}
################################ Main script ################################
run_tests=0
fetch_deps=1
unit_tests_only=0
# Process command-line arguments
while [[ $# -gt 0 ]] ; do
key="$1"
case $key in
-clean)
clean
;;
-help|-h)
display_usage
exit
;;
-test)
run_tests=1
;;
-tdd)
run_tests=1
fetch_deps=0
unit_tests_only=1
;;
*)
echo "$0: invalid option: $key"
display_usage
exit $EX_USAGE
esac
shift # past the processed argument
done
# Check if Node.JS/npm is installed.
type npm >/dev/null ||\
fail "Build environment setup error detected! Please ensure Node.js is installed!"
if (( fetch_deps )); then
# Before installing, ensure that the local npm package we need can be require()'d.
(cd $LEXICAL_MODELS_TYPES && npm link .) || fail "Could not link lexical-model-types"
echo "Dependencies check"
npm install --no-optional
fi
build || fail "Compilation failed."
echo "Typescript compilation successful."
if (( run_tests )); then
if (( unit_tests_only )); then
npm run test -- -headless || fail "Unit tests failed"
else
npm test || fail "Tests failed"
fi
fi