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