xref: /aosp_15_r20/external/cldr/docs/charts/keyboard/static/keyboard-chart.js (revision 912701f9769bb47905792267661f0baf2b85bed5)
1// helper functions for keyboard
2
3/**
4 * Unescape an escaped string
5 * @param str input string such as '\u017c'
6 * @returns
7 */
8function unescapeStr(str) {
9  str = str.replace(/\\u{([0-9a-fA-F]+)}/g, (a, b) =>
10    String.fromCodePoint(Number.parseInt(b, 16))
11  );
12  return str;
13}
14
15function getKeyboardLayers(id) {
16  let q = _KeyboardData.keyboards[id].keyboard3.layers;
17  if (!Array.isArray(q)) {
18    q = [q];
19  }
20  mogrifyAttrs(q);
21  const keybag = getKeyboardKeys(id);
22  mogrifyLayerList(q, keybag);
23  return q;
24}
25
26function mogrifyLayerList(layerList, keybag) {
27  layerList.forEach(({ layer }) => {
28    layer.forEach(({ row }) => {
29      row.forEach((r) => {
30        r.keys = r.keys.split(" ").map((id) =>
31          Object.assign(
32            {
33              id,
34            },
35            keybag[id]
36          )
37        );
38      });
39    });
40  });
41}
42
43function getImportFile(id) {
44  return _KeyboardData.imports[id["@_path"].split("/")[1]];
45}
46
47function getImportKeys(id) {
48  const imp = getImportFile(id);
49  if (!imp) {
50    throw Error(`Could not load import ${JSON.stringify(id)}`);
51  }
52  return imp.keys.key;
53}
54
55function mogrifyKeys(keys) {
56  // drop @'
57  if (!keys) {
58    return [];
59  }
60  return keys.reduce((p, v) => {
61    // TODO: any other swapping
62    mogrifyAttrs(v);
63    const { id, output } = v;
64    if (output) {
65      v.output = unescapeStr(output);
66    }
67    p[id] = v;
68    return p;
69  }, {});
70}
71
72function mogrifyAttrs(o) {
73  for (const k of Object.keys(o)) {
74    const ok = o[k];
75    if (/^@_/.test(k)) {
76      const attr = k.substring(2);
77      o[attr] = ok;
78      delete o[k];
79    } else if (Array.isArray(ok)) {
80      ok.forEach((e) => mogrifyAttrs(e));
81    } else if (typeof ok === "object") {
82      mogrifyAttrs(ok);
83    }
84  }
85  return o;
86}
87
88function getKeyboardKeys(id) {
89  const keys = _KeyboardData.keyboards[id].keyboard3.keys.key || [];
90  if (!keys) {
91    throw Error(`No keys for ${id}`);
92  }
93  let imports = [
94    {
95      // add implied import
96      "@_base": "cldr",
97      "@_path": "45/keys-Latn-implied.xml",
98    },
99    ...(_KeyboardData.keyboards[id].keyboard3.keys.import || []),
100  ];
101
102  const importedKeys = [];
103  for (const fn of imports) {
104    for (const k of getImportKeys(fn)) {
105      importedKeys.push(k);
106    }
107  }
108
109  return mogrifyKeys([...importedKeys, ...keys]);
110}
111
112function getIds() {
113  return Object.keys(_KeyboardData.keyboards);
114}
115