diff --git a/developer/src/kmldmlc/.gitignore b/developer/src/kmldmlc/.gitignore new file mode 100644 index 0000000000..bf1a402a3d --- /dev/null +++ b/developer/src/kmldmlc/.gitignore @@ -0,0 +1,2 @@ +tsconfig.tsbuildinfo +build/ \ No newline at end of file diff --git a/developer/src/kmldmlc/Makefile b/developer/src/kmldmlc/Makefile new file mode 100644 index 0000000000..d75e23a1e0 --- /dev/null +++ b/developer/src/kmldmlc/Makefile @@ -0,0 +1,37 @@ +# +# Keyman Developer - LDML Keyboard Compiler Makefile +# + +!include ..\Defines.mak + +configure: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh configure + +build: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh build + +clean: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh clean + +test: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh test + +bundle: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh bundle + +publish: .virtual + $(GIT_BASH_FOR_KEYMAN) build.sh publish + +signcode: + @rem nothing to do + +wrap-symbols: + @rem nothing to do + +test-manifest: + @rem nothing to do + +install: + @rem nothing to do + +!include ..\Target.mak diff --git a/developer/src/kmldmlc/README.md b/developer/src/kmldmlc/README.md new file mode 100644 index 0000000000..277883f851 --- /dev/null +++ b/developer/src/kmldmlc/README.md @@ -0,0 +1,44 @@ +Keyman Developer - LDML Keyboard Compiler +================ + +This package provides the following Keyman **command line tool**: + + - `kmldmlc` — takes **LDML Keyboard .xml sources** and compiles them in to a + KMXPlus **.kmx** file. + +Install +------- + +Install `kmlmdlc` globally: + + npm install -g @keymanapp/ldml-keyboard-compiler + +Usage +----- + +To compile a lexical model from its `.xml` source, use `kmldmlc`: + + kmldmlc my-keyboard.xml --outFile my-keyboard.kmx + +To see more command line options by using the `--help` option: + + kmldmlc --help + +How to build from source +------------------------ + +Run `build.sh`: + + ./build.sh configure build + + +How to run the tests +-------------------- + + ./build.sh test + + +How to prepare a bundle +----------------------- + + ./build.sh bundle diff --git a/developer/src/kmldmlc/build.sh b/developer/src/kmldmlc/build.sh new file mode 100644 index 0000000000..f3d4ef20e2 --- /dev/null +++ b/developer/src/kmldmlc/build.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +# +# Compiles the developer tools, including the language model compilers. +# + +# Exit on command failure and when using unset variables: +set -eu + +## START STANDARD BUILD SCRIPT INCLUDE +# adjust relative paths as necessary +THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")" +. "$(dirname "$THIS_SCRIPT")/../../../resources/build/build-utils.sh" +## END STANDARD BUILD SCRIPT INCLUDE + +cd "$THIS_SCRIPT_PATH" + +. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh" + +builder_describe "Build Keyman LDML Keyboard Compiler kmldmlc" \ + "configure runs 'npm ci' on root folder" \ + "build (default) builds kmldmlc to build/" \ + "clean cleans build/ folder" \ + "bundle creates a bundled version of kmldmlc" \ + "test run automated tests for kmldmlc" \ + "publish publish to npm" \ + "--dry-run ???" + +builder_parse "$@" + +#------------------------------------------------------------------------------------------------------------------- + +if builder_has_action configure; then + verify_npm_setup + builder_report success configure +fi + +#------------------------------------------------------------------------------------------------------------------- + +if builder_has_action clean; then + rm -rf ./build/ ./tsconfig.tsbuildinfo + builder_report success clean +fi + +#------------------------------------------------------------------------------------------------------------------- + +if builder_has_action build; then + npm run build + builder_report success build +fi + +#------------------------------------------------------------------------------------------------------------------- + +if builder_has_action test; then + npm test + builder_report success test +fi + +#------------------------------------------------------------------------------------------------------------------- + +if builder_has_action bundle; then + echo TODO: Bundle + builder_report success bundle +fi + +#------------------------------------------------------------------------------------------------------------------- + +if builder_has_action publish; then + if [[ $TIER == stable ]]; then + npm_dist_tag=latest + else + npm_dist_tag=$TIER + fi + + set_npm_version + + if build_has_option --dry-run; then + DRY_RUN=--dry-run + else + DRY_RUN= + fi + + #TEMP: we don't want to publish at this point! + DRY_RUN=--dry-run + + # Note: In either case, npm publish MUST be given --access public to publish + # a package in the @keymanapp scope on the public npm package index. + # + # See `npm help publish` for more details. + echo "Publishing $DRY_RUN npm package with tag $npm_dist_tag" + npm publish $DRY_RUN --access public --tag $npm_dist_tag || fail "Could not publish $npm_dist_tag release." + + builder_report success publish +fi diff --git a/developer/src/kmldmlc/package.json b/developer/src/kmldmlc/package.json new file mode 100644 index 0000000000..6f165626f5 --- /dev/null +++ b/developer/src/kmldmlc/package.json @@ -0,0 +1,40 @@ +{ + "name": "@keymanapp/ldml-keyboard-compiler", + "description": "Keyman Developer LDML keyboard compiler", + "keywords": [ + "keyboard", + "keyman", + "ldml", + "unicode" + ], + "scripts": { + "build": "tsc -b", + "test": "cd src/test && tsc -b && cd .. && mocha", + "prepublishOnly": "npm run build" + }, + "author": "Marc Durdin (https://github.com/mcdurdin)", + "license": "MIT", + "main": "build/kmldmlc.js", + "bin": { + "kmldmlc": "build/kmldmlc.js" + }, + "dependencies": { + "commander": "^3.0.0", + "typescript": "^4.5.4", + "xml2js": "^0.4.19" + }, + "devDependencies": { + "@keymanapp/keyman-version": "*", + "@types/chai": "^4.1.7", + "@types/mocha": "^5.2.7", + "@types/node": "^10.14.6", + "@types/xml2js": "^0.4.5", + "chai": "^4.3.4", + "chalk": "^2.4.2", + "mocha": "^8.4.0", + "ts-node": "^9.1.1" + }, + "mocha": { + "spec": "build-tests/**/test-*.js" + } +} diff --git a/developer/src/kmldmlc/src/keyman/ldmlkeyboard/compiler.ts b/developer/src/kmldmlc/src/keyman/ldmlkeyboard/compiler.ts new file mode 100644 index 0000000000..87f2477892 --- /dev/null +++ b/developer/src/kmldmlc/src/keyman/ldmlkeyboard/compiler.ts @@ -0,0 +1,20 @@ + +interface CompilerCallbacks { + loadFile(baseFilename:string, filename: string): Buffer; + reportMessage(severity: number, message: string): void; +}; + +export default class Compiler { + private callbacks: CompilerCallbacks; + constructor (callbacks: CompilerCallbacks) { + this.callbacks = callbacks; + + //TEMP + this.callbacks.reportMessage(0, "Instantiated compiler successfully"); + } + + public compile(filename: string): Buffer { + // TODO + return Buffer.from("KXTS..." + filename, 'utf8'); + } +} diff --git a/developer/src/kmldmlc/src/kmldmlc.ts b/developer/src/kmldmlc/src/kmldmlc.ts new file mode 100644 index 0000000000..f00976c9e4 --- /dev/null +++ b/developer/src/kmldmlc/src/kmldmlc.ts @@ -0,0 +1,62 @@ +#!/usr/bin/env node +/** + * kmldmlc - Keyman LDML Keyboard Compiler + */ + +import * as fs from 'fs'; +import * as path from 'path'; +import * as program from 'commander'; + +import Compiler from './keyman/ldmlkeyboard/compiler'; + +let inputFilename: string; + +const KEYMAN_VERSION = require("@keymanapp/keyman-version").KEYMAN_VERSION; + +/* Arguments */ +program + .description('Compiles Keyman LDML keyboards') + .version(KEYMAN_VERSION.VERSION_WITH_TAG) + .arguments('') + .action(infile => inputFilename = infile) + .option('-o, --outFile ', 'where to save the resulting .kmx file'); + +program.parse(process.argv); + +// Deal with input arguments: +if (!inputFilename) { + exitDueToUsageError('Must provide a LDML keyboard .xml source file.'); +} + +function exitDueToUsageError(message: string): never { + console.error(`${program._name}: ${message}`); + console.error(); + program.outputHelp(); + return process.exit(64); // TODO: SysExits.EX_USAGE +} + +class CompilerCallbacks { + loadFile(baseFilename: string, filename:string): Buffer { + // TODO: translate filename based on the baseFilename + return fs.readFileSync(filename); + } + reportMessage(severity: number, message: string): void { + console.log(message); + } +} + +function compileKeyboard(inputFilename: string): Buffer { + const c = new CompilerCallbacks(); + const k = new Compiler(c); + return k.compile(inputFilename); +} + +// Compile: +let code = compileKeyboard(inputFilename); + +// Output: + +if(code) { + const outFile = program.outFile ?? path.join(path.dirname(inputFilename), path.basename(inputFilename, '.xml') + '.kmx'); + fs.writeFileSync(outFile, code); +} diff --git a/developer/src/kmldmlc/tsconfig.json b/developer/src/kmldmlc/tsconfig.json new file mode 100644 index 0000000000..ccdb2efcfe --- /dev/null +++ b/developer/src/kmldmlc/tsconfig.json @@ -0,0 +1,26 @@ +{ + "extends": "../../../tsconfig-base.json", + + "compilerOptions": { + "module": "commonjs", + "target": "es2017", + "moduleResolution": "node", + "sourceMap": true, + "outDir": "build/", + "rootDir": "src/", + "declaration": true, + "alwaysStrict": true, + "noImplicitThis": true, + "noImplicitReturns": true, + "noImplicitAny": true, + "strictBindCallApply": true, + "strictFunctionTypes": true, + "noUnusedLocals": true + }, + "include": [ + "src/**/*.ts" + ], + "references": [ + { "path": "../../../common/web/keyman-version" }, + ] +}