xref: /aosp_15_r20/external/cldr/docs/charts/keyboard/build.mjs (revision 912701f9769bb47905792267661f0baf2b85bed5)
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