1*912701f9SAndroid Build Coastguard Worker// do the XML parsing and fs access in a build step 2*912701f9SAndroid Build Coastguard Worker 3*912701f9SAndroid Build Coastguard Workerimport { promises as fs } from "node:fs"; 4*912701f9SAndroid Build Coastguard Workerimport * as path from "node:path"; 5*912701f9SAndroid Build Coastguard Workerimport { XMLParser } from "fast-xml-parser"; 6*912701f9SAndroid Build Coastguard Worker 7*912701f9SAndroid Build Coastguard Workerconst KEYBOARD_PATH = "../../../keyboards/3.0"; 8*912701f9SAndroid Build Coastguard Workerconst IMPORT_PATH = "../../../keyboards/import"; 9*912701f9SAndroid Build Coastguard Workerconst DATA_PATH = "static/data"; 10*912701f9SAndroid Build Coastguard Worker 11*912701f9SAndroid Build Coastguard Workerasync function xmlList(basepath) { 12*912701f9SAndroid Build Coastguard Worker const dir = await fs.opendir(basepath); 13*912701f9SAndroid Build Coastguard Worker const xmls = []; 14*912701f9SAndroid Build Coastguard Worker for await (const ent of dir) { 15*912701f9SAndroid Build Coastguard Worker if (!ent.isFile() || !/\.xml$/.test(ent.name)) { 16*912701f9SAndroid Build Coastguard Worker continue; 17*912701f9SAndroid Build Coastguard Worker } 18*912701f9SAndroid Build Coastguard Worker xmls.push(ent.name); 19*912701f9SAndroid Build Coastguard Worker } 20*912701f9SAndroid Build Coastguard Worker return xmls; 21*912701f9SAndroid Build Coastguard Worker} 22*912701f9SAndroid Build Coastguard Worker 23*912701f9SAndroid Build Coastguard Worker/** 24*912701f9SAndroid Build Coastguard Worker * List of elements that are always arrays 25*912701f9SAndroid Build Coastguard Worker */ 26*912701f9SAndroid Build Coastguard Workerconst alwaysArray = [ 27*912701f9SAndroid Build Coastguard Worker "keyboard3.transforms", 28*912701f9SAndroid Build Coastguard Worker "keyboard3.transforms.transformGroup", 29*912701f9SAndroid Build Coastguard Worker "keyboard3.transforms.transformGroup.transform", 30*912701f9SAndroid Build Coastguard Worker]; 31*912701f9SAndroid Build Coastguard Worker 32*912701f9SAndroid Build Coastguard Worker/** 33*912701f9SAndroid Build Coastguard Worker * Loading helper for isArray 34*912701f9SAndroid Build Coastguard Worker * @param name 35*912701f9SAndroid Build Coastguard Worker * @param jpath 36*912701f9SAndroid Build Coastguard Worker * @param isLeafNode 37*912701f9SAndroid Build Coastguard Worker * @param isAttribute 38*912701f9SAndroid Build Coastguard Worker * @returns 39*912701f9SAndroid Build Coastguard Worker */ 40*912701f9SAndroid Build Coastguard Worker// eslint-disable-next-line @typescript-eslint/no-unused-vars 41*912701f9SAndroid Build Coastguard Workerconst isArray = (name, jpath, isLeafNode, isAttribute) => { 42*912701f9SAndroid Build Coastguard Worker if (alwaysArray.indexOf(jpath) !== -1) return true; 43*912701f9SAndroid Build Coastguard Worker return false; 44*912701f9SAndroid Build Coastguard Worker}; 45*912701f9SAndroid Build Coastguard Worker 46*912701f9SAndroid Build Coastguard Worker/** 47*912701f9SAndroid Build Coastguard Worker * Do the XML Transform given raw XML source 48*912701f9SAndroid Build Coastguard Worker * @param xml XML source for transforms. entire keyboard file. 49*912701f9SAndroid Build Coastguard Worker * @param source source text 50*912701f9SAndroid Build Coastguard Worker * @returns target text 51*912701f9SAndroid Build Coastguard Worker */ 52*912701f9SAndroid Build Coastguard Workerexport function parseXml(xml) { 53*912701f9SAndroid Build Coastguard Worker const parser = new XMLParser({ 54*912701f9SAndroid Build Coastguard Worker ignoreAttributes: false, 55*912701f9SAndroid Build Coastguard Worker isArray, 56*912701f9SAndroid Build Coastguard Worker }); 57*912701f9SAndroid Build Coastguard Worker const j = parser.parse(xml); 58*912701f9SAndroid Build Coastguard Worker return j; 59*912701f9SAndroid Build Coastguard Worker} 60*912701f9SAndroid Build Coastguard Worker 61*912701f9SAndroid Build Coastguard Workerasync function readFile(path) { 62*912701f9SAndroid Build Coastguard Worker return fs.readFile(path, "utf-8"); 63*912701f9SAndroid Build Coastguard Worker} 64*912701f9SAndroid Build Coastguard Worker 65*912701f9SAndroid Build Coastguard Workerasync function main() { 66*912701f9SAndroid Build Coastguard Worker const xmls = await xmlList(KEYBOARD_PATH); 67*912701f9SAndroid Build Coastguard Worker const keyboards = await packXmls(KEYBOARD_PATH, xmls); 68*912701f9SAndroid Build Coastguard Worker const importFiles = await xmlList(IMPORT_PATH); 69*912701f9SAndroid Build Coastguard Worker const imports = await packXmls(IMPORT_PATH, importFiles); 70*912701f9SAndroid Build Coastguard Worker 71*912701f9SAndroid Build Coastguard Worker const allData = { 72*912701f9SAndroid Build Coastguard Worker keyboards, 73*912701f9SAndroid Build Coastguard Worker imports, 74*912701f9SAndroid Build Coastguard Worker }; 75*912701f9SAndroid Build Coastguard Worker 76*912701f9SAndroid Build Coastguard Worker const outPath = path.join(DATA_PATH, "keyboard-data.json"); 77*912701f9SAndroid Build Coastguard Worker const outJsPath = path.join(DATA_PATH, "keyboard-data.js"); 78*912701f9SAndroid Build Coastguard Worker await fs.mkdir(DATA_PATH, { recursive: true }); 79*912701f9SAndroid Build Coastguard Worker const json = JSON.stringify(allData, null, " "); // indent, in case we need to read it 80*912701f9SAndroid Build Coastguard Worker await fs.writeFile(outPath, json, "utf-8"); 81*912701f9SAndroid Build Coastguard Worker await fs.writeFile(outJsPath, `const _KeyboardData = \n` + json); 82*912701f9SAndroid Build Coastguard Worker return { xmls, importFiles, outPath, outJsPath }; 83*912701f9SAndroid Build Coastguard Worker} 84*912701f9SAndroid Build Coastguard Worker 85*912701f9SAndroid Build Coastguard Workermain().then( 86*912701f9SAndroid Build Coastguard Worker (done) => console.dir({ done }), 87*912701f9SAndroid Build Coastguard Worker (err) => { 88*912701f9SAndroid Build Coastguard Worker console.error(err); 89*912701f9SAndroid Build Coastguard Worker process.exitCode = 1; 90*912701f9SAndroid Build Coastguard Worker } 91*912701f9SAndroid Build Coastguard Worker); 92*912701f9SAndroid Build Coastguard Worker 93*912701f9SAndroid Build Coastguard Workerasync function packXmls(basepath, xmls) { 94*912701f9SAndroid Build Coastguard Worker const allData = {}; 95*912701f9SAndroid Build Coastguard Worker for (const fn of xmls) { 96*912701f9SAndroid Build Coastguard Worker const fp = path.join(basepath, fn); 97*912701f9SAndroid Build Coastguard Worker const data = await readFile(fp); 98*912701f9SAndroid Build Coastguard Worker const parsed = parseXml(data); 99*912701f9SAndroid Build Coastguard Worker allData[fn] = parsed; 100*912701f9SAndroid Build Coastguard Worker } 101*912701f9SAndroid Build Coastguard Worker return allData; 102*912701f9SAndroid Build Coastguard Worker} 103