@predictive-text-studio/lexical-model-compiler
Version:
Keyman Developer lexical model compiler
124 lines • 5.34 kB
JavaScript
;
/// <reference path="kps-file.ts" />
/// <reference path="kmp-json-file.ts" />
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const path = require("path");
const xml2js = require("xml2js");
const JSZip = require("jszip");
let zip = JSZip();
class KmpCompiler {
transformKpsToKmpObject(kpsString) {
// Load the KPS data from XML as JS structured data.
let kpsPackage = (() => {
let a;
let parser = new xml2js.Parser({
tagNameProcessors: [xml2js.processors.firstCharLowerCase],
explicitArray: false
});
parser.parseString(kpsString, (e, r) => { a = r; });
return a;
})();
let kps = kpsPackage.package;
//
// To convert to kmp.json, we need to:
//
// 1. Unwrap arrays (and convert to array where single object)
// 2. Fix casing on `iD`
// 3. Rewrap info, keyboard.languages, lexicalModel.languages, startMenu.items elements
// 4. Convert options.followKeyboardVersion to a bool
// 5. Filenames need to be basenames (but this comes after processing)
//
// Helper functions
let kpsInfoToKmpInfo = function (info) {
let ni = {};
let keys = ['author', 'copyright', 'name', 'version', 'website'];
for (let element of keys) {
if (info[element]) {
ni[element] = { description: info[element]._ || info[element].toString() };
if (info[element].$ && info[element].$.URL)
ni[element].url = info[element].$.URL;
}
}
return ni;
};
let arrayWrap = function (a) {
if (Array.isArray(a)) {
return a;
}
return [a];
};
let kpsLanguagesToKmpLanguages = function (language) {
return language.map((element) => { return { name: element._, id: element.$.ID }; });
};
// Start to construct the kmp.json file from the .kps file
let kmp = {
system: kps.system,
options: {
followKeyboardVersion: kps.options.followKeyboardVersion === ''
}
};
// Fill in additional fields
let keys = ['executeProgram', 'graphicFile', 'msiFilename', 'msiOptions', 'readmeFile'];
for (let element of keys) {
if (kps.options[element]) {
// TypeScript thinks it's possible to assign to followKeyboardVersion (a
// boolean), but in reality, all of the other keys are strings.
// Politely inform TypeScript that it's okay to do this assignment:
kmp.options[element] = kps.options[element];
}
}
if (kps.info) {
kmp.info = kpsInfoToKmpInfo(kps.info);
}
if (kps.files && kps.files.file) {
kmp.files = arrayWrap(kps.files.file);
}
if (kps.keyboards && kps.keyboards.keyboard) {
kmp.keyboards = arrayWrap(kps.keyboards.keyboard).map((keyboard) => {
return { name: keyboard.name, id: keyboard.iD, version: keyboard.version, languages: kpsLanguagesToKmpLanguages(arrayWrap(keyboard.languages.language)) };
});
}
if (kps.lexicalModels && kps.lexicalModels.lexicalModel) {
kmp.lexicalModels = arrayWrap(kps.lexicalModels.lexicalModel).map((model) => {
return { name: model.name, id: model.iD, languages: kpsLanguagesToKmpLanguages(arrayWrap(model.languages.language)) };
});
}
if (kps.startMenu) {
kmp.startMenu = {};
if (kps.startMenu.addUninstallEntry)
kmp.startMenu.addUninstallEntry = kps.startMenu.addUninstallEntry === '';
if (kps.startMenu.folder)
kmp.startMenu.folder = kps.startMenu.folder;
if (kps.startMenu.items && kps.startMenu.items.item)
kmp.startMenu.items = arrayWrap(kps.startMenu.items.item);
}
if (kps.strings && kps.strings.string) {
kmp.strings = arrayWrap(kps.strings.string);
}
//let util = require('util');
//console.log(util.inspect(kmp, false, null))
//console.log(kps);
return kmp;
}
buildKmpFile(kmpJsonData, kmpFileName) {
const kmpJsonFileName = 'kmp.json';
if (!kmpJsonData.files) {
kmpJsonData.files = [];
}
kmpJsonData.files.forEach(function (value) {
// Make file path slashes compatible across platforms
let filename = value.name.replace(/\\/g, "/");
let data = fs.readFileSync(path.join('../source', filename), 'utf8');
zip.file(path.basename(filename), data);
// Remove path data from files before save
value.name = path.basename(filename);
});
zip.file(kmpJsonFileName, JSON.stringify(kmpJsonData, null, 2));
// Generate kmp file
var data = zip.generate({ base64: false, compression: 'DEFLATE' });
fs.writeFileSync(kmpFileName, data, 'binary');
}
}
exports.default = KmpCompiler;
//# sourceMappingURL=kmp-compiler.js.map