@keymanapp/common-types 17.0.85-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (248) hide show
  1. package/build/src/consts/virtual-key-constants.d.ts +131 -0
  2. package/build/src/consts/virtual-key-constants.d.ts.map +1 -0
  3. package/build/src/consts/virtual-key-constants.js +245 -0
  4. package/build/src/consts/virtual-key-constants.js.map +1 -0
  5. package/build/src/import/techpreview/cldr_info.json +5 -0
  6. package/build/src/import/techpreview/keys-Latn-implied.xml +80 -0
  7. package/build/src/import/techpreview/keys-Zyyy-currency.xml +22 -0
  8. package/build/src/import/techpreview/keys-Zyyy-punctuation.xml +46 -0
  9. package/build/src/keyman-touch-layout/keyman-touch-layout-file-reader.d.ts +7 -0
  10. package/build/src/keyman-touch-layout/keyman-touch-layout-file-reader.d.ts.map +1 -0
  11. package/build/src/keyman-touch-layout/keyman-touch-layout-file-reader.js +74 -0
  12. package/build/src/keyman-touch-layout/keyman-touch-layout-file-reader.js.map +1 -0
  13. package/build/src/keyman-touch-layout/keyman-touch-layout-file-writer.d.ts +24 -0
  14. package/build/src/keyman-touch-layout/keyman-touch-layout-file-writer.d.ts.map +1 -0
  15. package/build/src/keyman-touch-layout/keyman-touch-layout-file-writer.js +75 -0
  16. package/build/src/keyman-touch-layout/keyman-touch-layout-file-writer.js.map +1 -0
  17. package/build/src/keyman-touch-layout/keyman-touch-layout-file.d.ts +76 -0
  18. package/build/src/keyman-touch-layout/keyman-touch-layout-file.d.ts.map +1 -0
  19. package/build/src/keyman-touch-layout/keyman-touch-layout-file.js +26 -0
  20. package/build/src/keyman-touch-layout/keyman-touch-layout-file.js.map +1 -0
  21. package/build/src/keyman-touch-layout.clean.spec.json +170 -0
  22. package/build/src/kmx/element-string.d.ts +19 -0
  23. package/build/src/kmx/element-string.d.ts.map +1 -0
  24. package/build/src/kmx/element-string.js +72 -0
  25. package/build/src/kmx/element-string.js.map +1 -0
  26. package/build/src/kmx/kmx-builder.d.ts +77 -0
  27. package/build/src/kmx/kmx-builder.d.ts.map +1 -0
  28. package/build/src/kmx/kmx-builder.js +193 -0
  29. package/build/src/kmx/kmx-builder.js.map +1 -0
  30. package/build/src/kmx/kmx-plus-builder/build-disp.d.ts +18 -0
  31. package/build/src/kmx/kmx-plus-builder/build-disp.d.ts.map +1 -0
  32. package/build/src/kmx/kmx-plus-builder/build-disp.js +25 -0
  33. package/build/src/kmx/kmx-plus-builder/build-disp.js.map +1 -0
  34. package/build/src/kmx/kmx-plus-builder/build-elem.d.ts +26 -0
  35. package/build/src/kmx/kmx-plus-builder/build-elem.d.ts.map +1 -0
  36. package/build/src/kmx/kmx-plus-builder/build-elem.js +78 -0
  37. package/build/src/kmx/kmx-plus-builder/build-elem.js.map +1 -0
  38. package/build/src/kmx/kmx-plus-builder/build-keys.d.ts +60 -0
  39. package/build/src/kmx/kmx-plus-builder/build-keys.d.ts.map +1 -0
  40. package/build/src/kmx/kmx-plus-builder/build-keys.js +107 -0
  41. package/build/src/kmx/kmx-plus-builder/build-keys.js.map +1 -0
  42. package/build/src/kmx/kmx-plus-builder/build-layr.d.ts +54 -0
  43. package/build/src/kmx/kmx-plus-builder/build-layr.d.ts.map +1 -0
  44. package/build/src/kmx/kmx-plus-builder/build-layr.js +99 -0
  45. package/build/src/kmx/kmx-plus-builder/build-layr.js.map +1 -0
  46. package/build/src/kmx/kmx-plus-builder/build-list.d.ts +34 -0
  47. package/build/src/kmx/kmx-plus-builder/build-list.d.ts.map +1 -0
  48. package/build/src/kmx/kmx-plus-builder/build-list.js +62 -0
  49. package/build/src/kmx/kmx-plus-builder/build-list.js.map +1 -0
  50. package/build/src/kmx/kmx-plus-builder/build-loca.d.ts +12 -0
  51. package/build/src/kmx/kmx-plus-builder/build-loca.d.ts.map +1 -0
  52. package/build/src/kmx/kmx-plus-builder/build-loca.js +20 -0
  53. package/build/src/kmx/kmx-plus-builder/build-loca.js.map +1 -0
  54. package/build/src/kmx/kmx-plus-builder/build-meta.d.ts +17 -0
  55. package/build/src/kmx/kmx-plus-builder/build-meta.d.ts.map +1 -0
  56. package/build/src/kmx/kmx-plus-builder/build-meta.js +21 -0
  57. package/build/src/kmx/kmx-plus-builder/build-meta.js.map +1 -0
  58. package/build/src/kmx/kmx-plus-builder/build-name.d.ts +12 -0
  59. package/build/src/kmx/kmx-plus-builder/build-name.d.ts.map +1 -0
  60. package/build/src/kmx/kmx-plus-builder/build-name.js +23 -0
  61. package/build/src/kmx/kmx-plus-builder/build-name.js.map +1 -0
  62. package/build/src/kmx/kmx-plus-builder/build-ordr.d.ts +18 -0
  63. package/build/src/kmx/kmx-plus-builder/build-ordr.d.ts.map +1 -0
  64. package/build/src/kmx/kmx-plus-builder/build-ordr.js +27 -0
  65. package/build/src/kmx/kmx-plus-builder/build-ordr.js.map +1 -0
  66. package/build/src/kmx/kmx-plus-builder/build-sect.d.ts +16 -0
  67. package/build/src/kmx/kmx-plus-builder/build-sect.d.ts.map +1 -0
  68. package/build/src/kmx/kmx-plus-builder/build-sect.js +14 -0
  69. package/build/src/kmx/kmx-plus-builder/build-sect.js.map +1 -0
  70. package/build/src/kmx/kmx-plus-builder/build-strs.d.ts +18 -0
  71. package/build/src/kmx/kmx-plus-builder/build-strs.d.ts.map +1 -0
  72. package/build/src/kmx/kmx-plus-builder/build-strs.js +34 -0
  73. package/build/src/kmx/kmx-plus-builder/build-strs.js.map +1 -0
  74. package/build/src/kmx/kmx-plus-builder/build-tran.d.ts +20 -0
  75. package/build/src/kmx/kmx-plus-builder/build-tran.d.ts.map +1 -0
  76. package/build/src/kmx/kmx-plus-builder/build-tran.js +30 -0
  77. package/build/src/kmx/kmx-plus-builder/build-tran.js.map +1 -0
  78. package/build/src/kmx/kmx-plus-builder/build-vkey.d.ts +16 -0
  79. package/build/src/kmx/kmx-plus-builder/build-vkey.d.ts.map +1 -0
  80. package/build/src/kmx/kmx-plus-builder/build-vkey.js +23 -0
  81. package/build/src/kmx/kmx-plus-builder/build-vkey.js.map +1 -0
  82. package/build/src/kmx/kmx-plus-builder/builder-section.d.ts +6 -0
  83. package/build/src/kmx/kmx-plus-builder/builder-section.d.ts.map +1 -0
  84. package/build/src/kmx/kmx-plus-builder/builder-section.js +3 -0
  85. package/build/src/kmx/kmx-plus-builder/builder-section.js.map +1 -0
  86. package/build/src/kmx/kmx-plus-builder/kmx-plus-builder.d.ts +47 -0
  87. package/build/src/kmx/kmx-plus-builder/kmx-plus-builder.d.ts.map +1 -0
  88. package/build/src/kmx/kmx-plus-builder/kmx-plus-builder.js +143 -0
  89. package/build/src/kmx/kmx-plus-builder/kmx-plus-builder.js.map +1 -0
  90. package/build/src/kmx/kmx-plus.d.ts +259 -0
  91. package/build/src/kmx/kmx-plus.d.ts.map +1 -0
  92. package/build/src/kmx/kmx-plus.js +594 -0
  93. package/build/src/kmx/kmx-plus.js.map +1 -0
  94. package/build/src/kmx/kmx.d.ts +166 -0
  95. package/build/src/kmx/kmx.d.ts.map +1 -0
  96. package/build/src/kmx/kmx.js +271 -0
  97. package/build/src/kmx/kmx.js.map +1 -0
  98. package/build/src/kmx/string-list.d.ts +29 -0
  99. package/build/src/kmx/string-list.d.ts.map +1 -0
  100. package/build/src/kmx/string-list.js +75 -0
  101. package/build/src/kmx/string-list.js.map +1 -0
  102. package/build/src/kpj/keyman-developer-project.d.ts +58 -0
  103. package/build/src/kpj/keyman-developer-project.d.ts.map +1 -0
  104. package/build/src/kpj/keyman-developer-project.js +141 -0
  105. package/build/src/kpj/keyman-developer-project.js.map +1 -0
  106. package/build/src/kpj/kpj-file-reader.d.ts +17 -0
  107. package/build/src/kpj/kpj-file-reader.d.ts.map +1 -0
  108. package/build/src/kpj/kpj-file-reader.js +92 -0
  109. package/build/src/kpj/kpj-file-reader.js.map +1 -0
  110. package/build/src/kpj/kpj-file.d.ts +39 -0
  111. package/build/src/kpj/kpj-file.d.ts.map +1 -0
  112. package/build/src/kpj/kpj-file.js +11 -0
  113. package/build/src/kpj/kpj-file.js.map +1 -0
  114. package/build/src/kpj.schema.json +127 -0
  115. package/build/src/kvk/kvk-file-reader.d.ts +5 -0
  116. package/build/src/kvk/kvk-file-reader.d.ts.map +1 -0
  117. package/build/src/kvk/kvk-file-reader.js +35 -0
  118. package/build/src/kvk/kvk-file-reader.js.map +1 -0
  119. package/build/src/kvk/kvk-file-writer.d.ts +20 -0
  120. package/build/src/kvk/kvk-file-writer.d.ts.map +1 -0
  121. package/build/src/kvk/kvk-file-writer.js +67 -0
  122. package/build/src/kvk/kvk-file-writer.js.map +1 -0
  123. package/build/src/kvk/kvk-file.d.ts +64 -0
  124. package/build/src/kvk/kvk-file.d.ts.map +1 -0
  125. package/build/src/kvk/kvk-file.js +63 -0
  126. package/build/src/kvk/kvk-file.js.map +1 -0
  127. package/build/src/kvk/kvks-file-reader.d.ts +30 -0
  128. package/build/src/kvk/kvks-file-reader.d.ts.map +1 -0
  129. package/build/src/kvk/kvks-file-reader.js +154 -0
  130. package/build/src/kvk/kvks-file-reader.js.map +1 -0
  131. package/build/src/kvk/kvks-file-writer.d.ts +6 -0
  132. package/build/src/kvk/kvks-file-writer.d.ts.map +1 -0
  133. package/build/src/kvk/kvks-file-writer.js +99 -0
  134. package/build/src/kvk/kvks-file-writer.js.map +1 -0
  135. package/build/src/kvk/kvks-file.d.ts +44 -0
  136. package/build/src/kvk/kvks-file.d.ts.map +1 -0
  137. package/build/src/kvk/kvks-file.js +10 -0
  138. package/build/src/kvk/kvks-file.js.map +1 -0
  139. package/build/src/kvk/visual-keyboard.d.ts +35 -0
  140. package/build/src/kvk/visual-keyboard.d.ts.map +1 -0
  141. package/build/src/kvk/visual-keyboard.js +61 -0
  142. package/build/src/kvk/visual-keyboard.js.map +1 -0
  143. package/build/src/kvks.schema.json +182 -0
  144. package/build/src/ldml-keyboard/ldml-keyboard-testdata-xml.d.ts +56 -0
  145. package/build/src/ldml-keyboard/ldml-keyboard-testdata-xml.d.ts.map +1 -0
  146. package/build/src/ldml-keyboard/ldml-keyboard-testdata-xml.js +20 -0
  147. package/build/src/ldml-keyboard/ldml-keyboard-testdata-xml.js.map +1 -0
  148. package/build/src/ldml-keyboard/ldml-keyboard-xml-reader.d.ts +91 -0
  149. package/build/src/ldml-keyboard/ldml-keyboard-xml-reader.d.ts.map +1 -0
  150. package/build/src/ldml-keyboard/ldml-keyboard-xml-reader.js +370 -0
  151. package/build/src/ldml-keyboard/ldml-keyboard-xml-reader.js.map +1 -0
  152. package/build/src/ldml-keyboard/ldml-keyboard-xml.d.ts +143 -0
  153. package/build/src/ldml-keyboard/ldml-keyboard-xml.d.ts.map +1 -0
  154. package/build/src/ldml-keyboard/ldml-keyboard-xml.js +34 -0
  155. package/build/src/ldml-keyboard/ldml-keyboard-xml.js.map +1 -0
  156. package/build/src/ldml-keyboard.schema.json +634 -0
  157. package/build/src/ldml-keyboardtest.schema.json +221 -0
  158. package/build/src/main.d.ts +21 -0
  159. package/build/src/main.d.ts.map +1 -0
  160. package/build/src/main.js +20 -0
  161. package/build/src/main.js.map +1 -0
  162. package/build/src/util/common-events.d.ts +49 -0
  163. package/build/src/util/common-events.d.ts.map +1 -0
  164. package/build/src/util/common-events.js +29 -0
  165. package/build/src/util/common-events.js.map +1 -0
  166. package/build/src/util/compiler-interfaces.d.ts +51 -0
  167. package/build/src/util/compiler-interfaces.d.ts.map +1 -0
  168. package/build/src/util/compiler-interfaces.js +33 -0
  169. package/build/src/util/compiler-interfaces.js.map +1 -0
  170. package/build/src/util/util.d.ts +17 -0
  171. package/build/src/util/util.d.ts.map +1 -0
  172. package/build/src/util/util.js +67 -0
  173. package/build/src/util/util.js.map +1 -0
  174. package/build/tsconfig.tsbuildinfo +1 -0
  175. package/build.sh +86 -0
  176. package/package.json +58 -0
  177. package/src/consts/virtual-key-constants.ts +257 -0
  178. package/src/keyman-touch-layout/keyman-touch-layout-file-reader.ts +81 -0
  179. package/src/keyman-touch-layout/keyman-touch-layout-file-writer.ts +84 -0
  180. package/src/keyman-touch-layout/keyman-touch-layout-file.ts +87 -0
  181. package/src/kmx/element-string.ts +79 -0
  182. package/src/kmx/kmx-builder.ts +287 -0
  183. package/src/kmx/kmx-plus-builder/build-disp.ts +46 -0
  184. package/src/kmx/kmx-plus-builder/build-elem.ts +103 -0
  185. package/src/kmx/kmx-plus-builder/build-keys.ts +175 -0
  186. package/src/kmx/kmx-plus-builder/build-layr.ts +154 -0
  187. package/src/kmx/kmx-plus-builder/build-list.ts +95 -0
  188. package/src/kmx/kmx-plus-builder/build-loca.ts +34 -0
  189. package/src/kmx/kmx-plus-builder/build-meta.ts +37 -0
  190. package/src/kmx/kmx-plus-builder/build-name.ts +37 -0
  191. package/src/kmx/kmx-plus-builder/build-ordr.ts +45 -0
  192. package/src/kmx/kmx-plus-builder/build-sect.ts +31 -0
  193. package/src/kmx/kmx-plus-builder/build-strs.ts +58 -0
  194. package/src/kmx/kmx-plus-builder/build-tran.ts +50 -0
  195. package/src/kmx/kmx-plus-builder/build-vkey.ts +43 -0
  196. package/src/kmx/kmx-plus-builder/builder-section.ts +6 -0
  197. package/src/kmx/kmx-plus-builder/kmx-plus-builder.ts +190 -0
  198. package/src/kmx/kmx-plus.ts +692 -0
  199. package/src/kmx/kmx.ts +360 -0
  200. package/src/kmx/string-list.ts +74 -0
  201. package/src/kpj/keyman-developer-project.ts +155 -0
  202. package/src/kpj/kpj-file-reader.ts +103 -0
  203. package/src/kpj/kpj-file.ts +52 -0
  204. package/src/kvk/kvk-file-reader.ts +34 -0
  205. package/src/kvk/kvk-file-writer.ts +72 -0
  206. package/src/kvk/kvk-file.ts +122 -0
  207. package/src/kvk/kvks-file-reader.ts +164 -0
  208. package/src/kvk/kvks-file-writer.ts +113 -0
  209. package/src/kvk/kvks-file.ts +53 -0
  210. package/src/kvk/visual-keyboard.ts +80 -0
  211. package/src/ldml-keyboard/ldml-keyboard-testdata-xml.ts +74 -0
  212. package/src/ldml-keyboard/ldml-keyboard-xml-reader.ts +387 -0
  213. package/src/ldml-keyboard/ldml-keyboard-xml.ts +177 -0
  214. package/src/main.ts +27 -0
  215. package/src/restructure.d.ts +2 -0
  216. package/src/util/common-events.ts +50 -0
  217. package/src/util/compiler-interfaces.ts +54 -0
  218. package/src/util/util.ts +68 -0
  219. package/test/fixtures/import-minimal.xml +8 -0
  220. package/test/fixtures/import-minimal1.xml +11 -0
  221. package/test/fixtures/import-minimal2.xml +11 -0
  222. package/test/fixtures/import-symbols.xml +13 -0
  223. package/test/fixtures/invalid-conforms-to.xml +19 -0
  224. package/test/fixtures/invalid-import-base.xml +16 -0
  225. package/test/fixtures/invalid-import-path.xml +16 -0
  226. package/test/fixtures/invalid-import-readfail.xml +16 -0
  227. package/test/fixtures/invalid-import-wrongroot.xml +16 -0
  228. package/test/fixtures/invalid-structure-per-dtd.xml +8 -0
  229. package/test/fixtures/keyman-touch-layout/khmer_angkor.keyman-touch-layout +1950 -0
  230. package/test/fixtures/keyman-touch-layout/legacy.keyman-touch-layout +36 -0
  231. package/test/fixtures/kpj/khmer_angkor.kpj +187 -0
  232. package/test/fixtures/kvk/khmer_angkor.kvk +0 -0
  233. package/test/fixtures/kvk/khmer_angkor.kvks +206 -0
  234. package/test/fixtures/test-fr.xml +22 -0
  235. package/test/helpers/index.ts +39 -0
  236. package/test/helpers/reader-callback-test.ts +199 -0
  237. package/test/keyman-touch-layout/test-keyman-touch-layout-file-reader.ts +71 -0
  238. package/test/keyman-touch-layout/test-keyman-touch-layout-round-trip.ts +35 -0
  239. package/test/kpj/test-kpj-file-reader.ts +123 -0
  240. package/test/kvk/test-kvk-file.ts +15 -0
  241. package/test/kvk/test-kvk-round-trip.ts +87 -0
  242. package/test/kvk/test-kvk-utils.ts +24 -0
  243. package/test/kvk/test-kvks-file.ts +45 -0
  244. package/test/ldml-keyboard/test-ldml-keyboard-testdata-reader.ts +51 -0
  245. package/test/ldml-keyboard/test-ldml-keyboard-xml-reader.ts +131 -0
  246. package/test/tsconfig.json +21 -0
  247. package/test/util/test-unescape.ts +38 -0
  248. package/tsconfig.json +17 -0
package/src/kmx/kmx.ts ADDED
@@ -0,0 +1,360 @@
1
+ import * as r from 'restructure';
2
+
3
+ /* Definitions from kmx_file.h. Must be kept in sync */
4
+
5
+ // TODO: split kmx-file from kmx in-memory, similar to what I've done for kvk (keep restructure decl + BUILDER_ interfaces together)
6
+
7
+ // In memory representations of KMX structures
8
+ // kmx-builder will transform these to the corresponding COMP_xxxx
9
+
10
+ export class KEYBOARD {
11
+ //TODO: additional header fields
12
+ groups: GROUP[];
13
+ stores: STORE[];
14
+ };
15
+
16
+ export class STORE {
17
+ dwSystemID: number;
18
+ dpName: string;
19
+ dpString: string;
20
+ };
21
+
22
+ export class GROUP {
23
+ dpName: string;
24
+ keys: KEY[];
25
+ dpMatch: string;
26
+ dpNoMatch: string;
27
+ fUsingKeys: boolean;
28
+ };
29
+
30
+ export class KEY {
31
+ Key: number;
32
+ Line: number;
33
+ ShiftFlags: number;
34
+ dpOutput: string;
35
+ dpContext: string;
36
+ };
37
+
38
+
39
+ export class KMXFile {
40
+
41
+ /* KMX file structures */
42
+
43
+ public readonly COMP_STORE: any;
44
+ public readonly COMP_KEY: any;
45
+ public readonly COMP_GROUP: any;
46
+ public readonly COMP_KEYBOARD_KMXPLUSINFO: any;
47
+ public readonly COMP_KEYBOARD: any;
48
+
49
+ public static readonly FILEID_COMPILED = 0x5354584B; // 'KXTS'
50
+
51
+ //
52
+ // File version identifiers (COMP_KEYBOARD.dwFileVersion)
53
+ //
54
+
55
+ public static readonly VERSION_30 = 0x00000300;
56
+ public static readonly VERSION_31 = 0x00000301;
57
+ public static readonly VERSION_32 = 0x00000302;
58
+ public static readonly VERSION_40 = 0x00000400;
59
+ public static readonly VERSION_50 = 0x00000500;
60
+ public static readonly VERSION_501 = 0x00000501;
61
+ public static readonly VERSION_60 = 0x00000600;
62
+ public static readonly VERSION_70 = 0x00000700;
63
+ public static readonly VERSION_80 = 0x00000800;
64
+ public static readonly VERSION_90 = 0x00000900;
65
+ public static readonly VERSION_100 = 0x00000A00;
66
+ public static readonly VERSION_140 = 0x00000E00;
67
+ public static readonly VERSION_150 = 0x00000F00;
68
+
69
+ public static readonly VERSION_160 = 0x00001000;
70
+
71
+ public static readonly VERSION_MIN = this.VERSION_50;
72
+ public static readonly VERSION_MAX = this.VERSION_160;
73
+
74
+ //
75
+ // Backspace types
76
+ //
77
+
78
+ public static readonly BK_DEFAULT = 0;
79
+ public static readonly BK_DEADKEY = 1;
80
+
81
+ // Different begin types (COMP_STORE.StartGroup_*)
82
+
83
+ public static readonly BEGIN_ANSI = 0;
84
+ public static readonly BEGIN_UNICODE = 1;
85
+
86
+ //
87
+ // System Store values (COMP_STORE.dwSystemID)
88
+ //
89
+
90
+ public static readonly TSS_NONE = 0;
91
+ public static readonly TSS_BITMAP = 1;
92
+ public static readonly TSS_COPYRIGHT = 2;
93
+ public static readonly TSS_HOTKEY = 3;
94
+ public static readonly TSS_LANGUAGE = 4;
95
+ public static readonly TSS_LAYOUT = 5;
96
+ public static readonly TSS_MESSAGE = 6;
97
+ public static readonly TSS_NAME = 7;
98
+ public static readonly TSS_VERSION = 8;
99
+ public static readonly TSS_CAPSONONLY = 9;
100
+ public static readonly TSS_CAPSALWAYSOFF = 10;
101
+ public static readonly TSS_SHIFTFREESCAPS = 11;
102
+ public static readonly TSS_LANGUAGENAME = 12;
103
+
104
+ public static readonly TSS_CALLDEFINITION = 13;
105
+ public static readonly TSS_CALLDEFINITION_LOADFAILED = 14;
106
+
107
+ public static readonly TSS_ETHNOLOGUECODE = 15;
108
+
109
+ public static readonly TSS_DEBUG_LINE = 16;
110
+
111
+ public static readonly TSS_MNEMONIC = 17;
112
+
113
+ public static readonly TSS_INCLUDECODES = 18;
114
+
115
+ public static readonly TSS_OLDCHARPOSMATCHING = 19;
116
+
117
+ public static readonly TSS_COMPILEDVERSION = 20;
118
+ public static readonly TSS_KEYMANCOPYRIGHT = 21;
119
+
120
+ public static readonly TSS_CUSTOMKEYMANEDITION = 22;
121
+ public static readonly TSS_CUSTOMKEYMANEDITIONNAME = 23;
122
+
123
+ /* Keyman 7.0 system stores */
124
+
125
+ public static readonly TSS__KEYMAN_60_MAX = 23;
126
+
127
+ public static readonly TSS_VISUALKEYBOARD = 24;
128
+ public static readonly TSS_KMW_RTL = 25;
129
+ public static readonly TSS_KMW_HELPFILE = 26;
130
+ public static readonly TSS_KMW_HELPTEXT = 27;
131
+ public static readonly TSS_KMW_EMBEDJS = 28;
132
+
133
+ public static readonly TSS_WINDOWSLANGUAGES = 29;
134
+
135
+ public static readonly TSS__KEYMAN_70_MAX = 29;
136
+
137
+ /* Keyman 8.0 system stores */
138
+
139
+ public static readonly TSS_COMPARISON = 30;
140
+
141
+ public static readonly TSS__KEYMAN_80_MAX = 30;
142
+
143
+ /* Keyman 9.0 system stores */
144
+
145
+ public static readonly TSS_PLATFORM = 31;
146
+ public static readonly TSS_BASELAYOUT = 32;
147
+ public static readonly TSS_LAYER = 33;
148
+
149
+ public static readonly TSS_PLATFORM_NOMATCH = 0x8001; // Reserved for internal use - after platform statement is run, set to either TSS_PLATFORM_NOMATCH or TSS_PLATFORM_MATCH
150
+ public static readonly TSS_PLATFORM_MATCH = 0x8002; // Reserved for internal use - as the result will never change for the lifetime of the process.
151
+
152
+ public static readonly TSS_VKDICTIONARY = 34; // Dictionary of virtual key names for v9 dynamic layouts
153
+ public static readonly TSS_LAYOUTFILE = 35; // Keyman 9 layer-based JSON OSK
154
+ public static readonly TSS_KEYBOARDVERSION = 36; // &keyboardversion system store // I4140
155
+ public static readonly TSS_KMW_EMBEDCSS = 37;
156
+
157
+ public static readonly TSS_TARGETS = 38;
158
+
159
+ public static readonly TSS__KEYMAN_90_MAX = 38;
160
+
161
+ /* Keyman 14.0 system stores */
162
+
163
+ public static readonly TSS_CASEDKEYS = 39;
164
+
165
+ public static readonly TSS__KEYMAN_140_MAX = 39;
166
+
167
+ /* Keyman 15.0 system stores */
168
+
169
+ public static readonly TSS_BEGIN_NEWCONTEXT = 40;
170
+ public static readonly TSS_BEGIN_POSTKEYSTROKE = 41;
171
+ public static readonly TSS_NEWLAYER = 42;
172
+ public static readonly TSS_OLDLAYER = 43;
173
+
174
+ public static readonly TSS__KEYMAN_150_MAX = 43;
175
+
176
+ public static readonly TSS__MAX = 43;
177
+
178
+
179
+ public static readonly UC_SENTINEL = 0xFFFF;
180
+ public static readonly UC_SENTINEL_EXTENDEDEND = 0x10;
181
+
182
+ public static readonly U_UC_SENTINEL = "\uFFFF";
183
+
184
+ //
185
+ // VK__MAX defines the highest virtual key code defined in the system = 0xFF. Custom VK codes start at 256
186
+ //
187
+
188
+ public static readonly VK__MAX = 255;
189
+
190
+ //
191
+ // Extended String CODE_ values
192
+ //
193
+
194
+ public static readonly CODE_ANY = 0x01;
195
+ public static readonly CODE_INDEX = 0x02;
196
+ public static readonly CODE_CONTEXT = 0x03;
197
+ public static readonly CODE_NUL = 0x04;
198
+ public static readonly CODE_USE = 0x05;
199
+ public static readonly CODE_RETURN = 0x06;
200
+ public static readonly CODE_BEEP = 0x07;
201
+ public static readonly CODE_DEADKEY = 0x08;
202
+ // 0x09 = bkspace.-- we don't need to keep this separate though with UC_SENTINEL
203
+ public static readonly CODE_EXTENDED = 0x0A;
204
+ //public static readonly CODE_EXTENDEDEND = 0x0B; deprecated
205
+ public static readonly CODE_SWITCH = 0x0C;
206
+ public static readonly CODE_KEY = 0x0D;
207
+ public static readonly CODE_CLEARCONTEXT = 0x0E;
208
+ public static readonly CODE_CALL = 0x0F;
209
+ // UC_SENTINEL_EXTENDEDEND 0x10
210
+ public static readonly CODE_CONTEXTEX = 0x11;
211
+
212
+ public static readonly CODE_NOTANY = 0x12;
213
+
214
+ public static readonly CODE_KEYMAN70_LASTCODE = 0x12;
215
+
216
+ public static readonly CODE_SETOPT = 0x13;
217
+ public static readonly CODE_IFOPT = 0x14;
218
+ public static readonly CODE_SAVEOPT = 0x15;
219
+ public static readonly CODE_RESETOPT = 0x16;
220
+
221
+ public static readonly CODE_KEYMAN80_LASTCODE = 0x16;
222
+
223
+ /* Keyman 9.0 codes */
224
+
225
+ public static readonly CODE_IFSYSTEMSTORE = 0x17;
226
+ public static readonly CODE_SETSYSTEMSTORE = 0x18;
227
+
228
+ public static readonly CODE_LASTCODE = 0x18;
229
+
230
+
231
+ public static readonly KF_SHIFTFREESCAPS = 0x0001;
232
+ public static readonly KF_CAPSONONLY = 0x0002;
233
+ public static readonly KF_CAPSALWAYSOFF = 0x0004;
234
+ public static readonly KF_LOGICALLAYOUT = 0x0008;
235
+ public static readonly KF_AUTOMATICVERSION = 0x0010;
236
+
237
+ // 16.0: Support for LDML Keyboards in KMXPlus file format
238
+ public static readonly KF_KMXPLUS = 0x0020;
239
+
240
+ public static readonly HK_ALT = 0x00010000;
241
+ public static readonly HK_CTRL = 0x00020000;
242
+ public static readonly HK_SHIFT = 0x00040000;
243
+
244
+ public static readonly LCTRLFLAG = 0x0001; // Left Control flag
245
+ public static readonly RCTRLFLAG = 0x0002; // Right Control flag
246
+ public static readonly LALTFLAG = 0x0004; // Left Alt flag
247
+ public static readonly RALTFLAG = 0x0008; // Right Alt flag
248
+ public static readonly K_SHIFTFLAG = 0x0010; // Either shift flag
249
+ public static readonly K_CTRLFLAG = 0x0020; // Either ctrl flag
250
+ public static readonly K_ALTFLAG = 0x0040; // Either alt flag
251
+ //public static readonly K_METAFLAG = 0x0080; // Either Meta-key flag (tentative). Not usable in keyboard rules;
252
+ // Used internally (currently, only by KMW) to ensure Meta-key
253
+ // shortcuts safely bypass rules
254
+ // Meta key = Command key on macOS, Windows key on Windows
255
+ public static readonly CAPITALFLAG = 0x0100; // Caps lock on
256
+ public static readonly NOTCAPITALFLAG = 0x0200; // Caps lock NOT on
257
+ public static readonly NUMLOCKFLAG = 0x0400; // Num lock on
258
+ public static readonly NOTNUMLOCKFLAG = 0x0800; // Num lock NOT on
259
+ public static readonly SCROLLFLAG = 0x1000; // Scroll lock on
260
+ public static readonly NOTSCROLLFLAG = 0x2000; // Scroll lock NOT on
261
+ public static readonly ISVIRTUALKEY = 0x4000; // It is a Virtual Key Sequence
262
+ public static readonly VIRTUALCHARKEY = 0x8000; // Keyman 6.0: Virtual Key Cap Sequence NOT YET
263
+
264
+ public static readonly K_MODIFIERFLAG = 0x007F;
265
+ public static readonly K_NOTMODIFIERFLAG = 0xFF00; // I4548
266
+
267
+ public static readonly COMP_KEYBOARD_SIZE = 64;
268
+ public static readonly COMP_KEYBOARD_KMXPLUSINFO_SIZE = 8;
269
+ public static readonly COMP_STORE_SIZE = 12;
270
+ public static readonly COMP_GROUP_SIZE = 24;
271
+ public static readonly COMP_KEY_SIZE = 20;
272
+
273
+ /* In-memory representation of the keyboard */
274
+
275
+ public keyboard: KEYBOARD = {
276
+ groups: [],
277
+ stores: []
278
+ };
279
+
280
+ constructor() {
281
+
282
+ // Binary-correct structures matching kmx_file.h
283
+
284
+ this.COMP_STORE = new r.Struct({
285
+ dwSystemID: r.uint32le,
286
+ dpName: r.uint32le,
287
+ dpString: r.uint32le
288
+ });
289
+
290
+ if(this.COMP_STORE.size() != KMXFile.COMP_STORE_SIZE) {
291
+ throw "COMP_STORE size is "+this.COMP_STORE.size()+" but should be "+KMXFile.COMP_STORE_SIZE+" bytes";
292
+ }
293
+
294
+ this.COMP_KEY = new r.Struct({
295
+ Key: r.uint16le,
296
+ _padding: new r.Reserved(r.uint16le), // padding
297
+ Line: r.uint32le,
298
+ ShiftFlags: r.uint32le,
299
+ dpOutput: r.uint32le,
300
+ dpContext: r.uint32le
301
+ });
302
+
303
+ if(this.COMP_KEY.size() != KMXFile.COMP_KEY_SIZE) {
304
+ throw "COMP_KEY size is "+this.COMP_KEY.size()+" but should be "+KMXFile.COMP_KEY_SIZE+" bytes";
305
+ }
306
+
307
+ this.COMP_GROUP = new r.Struct({
308
+ dpName: r.uint32le,
309
+ dpKeyArray: r.uint32le, // [LPKEY] address of first item in key array
310
+ dpMatch: r.uint32le,
311
+ dpNoMatch: r.uint32le,
312
+ cxKeyArray: r.uint32le, // in array entries
313
+ fUsingKeys: r.uint32le // group(xx) [using keys] <-- specified or not
314
+ });
315
+
316
+ if(this.COMP_GROUP.size() != KMXFile.COMP_GROUP_SIZE) {
317
+ throw "COMP_GROUP size is "+this.COMP_GROUP.size()+" but should be "+KMXFile.COMP_GROUP_SIZE+" bytes";
318
+ }
319
+
320
+ this.COMP_KEYBOARD_KMXPLUSINFO = new r.Struct({
321
+ dpKMXPlus: r.uint32le, // 0040 offset of KMXPlus data, <sect> header is first
322
+ dwKMXPlusSize: r.uint32le // 0044 size in bytes of entire KMXPlus data
323
+ });
324
+
325
+ if(this.COMP_KEYBOARD_KMXPLUSINFO.size() != KMXFile.COMP_KEYBOARD_KMXPLUSINFO_SIZE) {
326
+ throw "COMP_KEYBOARD_KMXPLUSINFO size is "+this.COMP_KEYBOARD_KMXPLUSINFO.size()+" but should be "+KMXFile.COMP_KEYBOARD_KMXPLUSINFO_SIZE+" bytes";
327
+ }
328
+
329
+ this.COMP_KEYBOARD = new r.Struct({
330
+ dwIdentifier: r.uint32le, // 0000 Keyman compiled keyboard id
331
+
332
+ dwFileVersion: r.uint32le, // 0004 Version of the file - Keyman 4.0 is 0x0400
333
+
334
+ dwCheckSum: r.uint32le, // 0008 As stored in keyboard
335
+ KeyboardID: r.uint32le, // 000C as stored in HKEY_LOCAL_MACHINE//system//currentcontrolset//control//keyboard layouts
336
+ IsRegistered: r.uint32le, // 0010
337
+ version: r.uint32le, // 0014 keyboard version
338
+
339
+ cxStoreArray: r.uint32le, // 0018 in array entries
340
+ cxGroupArray: r.uint32le, // 001C in array entries
341
+
342
+ dpStoreArray: r.uint32le, // 0020 [LPSTORE] address of first item in store array
343
+ dpGroupArray: r.uint32le, // 0024 [LPGROUP] address of first item in group array
344
+
345
+ StartGroup_ANSI: r.uint32le, // 0028 index of starting ANSI group
346
+ StartGroup_Unicode: r.uint32le, // 0028 index of starting Unicode groups
347
+
348
+ dwFlags: r.uint32le, // 0030 Flags for the keyboard file
349
+
350
+ dwHotKey: r.uint32le, // 0034 standard windows hotkey (hiword=shift/ctrl/alt stuff, loword=vkey)
351
+
352
+ dpBitmapOffset: r.uint32le, // 0038 offset of the bitmaps in the file
353
+ dwBitmapSize: r.uint32le // 003C size in bytes of the bitmaps
354
+ });
355
+
356
+ if(this.COMP_KEYBOARD.size() != KMXFile.COMP_KEYBOARD_SIZE) {
357
+ throw "COMP_KEYBOARD size is "+this.COMP_KEYBOARD.size()+" but should be "+KMXFile.COMP_KEYBOARD_SIZE+" bytes";
358
+ }
359
+ }
360
+ }
@@ -0,0 +1,74 @@
1
+ import { Strs, StrsItem } from './kmx-plus.js';
2
+
3
+ /**
4
+ * A single entry in a ListItem.
5
+ * Contains a StrsItem as its value.
6
+ */
7
+ export class ListIndex {
8
+ readonly value: StrsItem; // will become index into Strs table
9
+ constructor(value: StrsItem) {
10
+ this.value = value;
11
+ }
12
+ isEqual(a: ListIndex | string) {
13
+ // so we can compare this to a string
14
+ return a.toString() === this.toString();
15
+ }
16
+ toString(): string {
17
+ return this.value.value;
18
+ }
19
+ };
20
+
21
+ /**
22
+ * A string list in memory. This will be replaced with an index
23
+ * into the string table at finalization.
24
+ */
25
+ export class ListItem extends Array<ListIndex> {
26
+ /**
27
+ * Construct a new list from an array of strings.
28
+ * Use List. This is meant to be called by the List.allocString*() functions.
29
+ * @param strs the Strs section is needed to construct this object.
30
+ * @param source array of strings
31
+ * @returns
32
+ */
33
+ constructor(strs: Strs, source: Array<string>) {
34
+ super();
35
+ if(!source) {
36
+ return;
37
+ }
38
+
39
+ for (const str of source) {
40
+ let index = new ListIndex(strs.allocString(str));
41
+ this.push(index);
42
+ }
43
+ }
44
+ isEqual(a: ListItem | string[]): boolean {
45
+ if (a.length != this.length) {
46
+ return false;
47
+ }
48
+ for (let i = 0; i < a.length; i++) {
49
+ if (!this[i].isEqual(a[i])) {
50
+ return false;
51
+ }
52
+ }
53
+ return true;
54
+ }
55
+ compareTo(o: ListItem): number {
56
+ for (let i = 0; i < Math.min(this.length, o.length); i++) {
57
+ const r = this[i].value.compareTo(o[i].value);
58
+ if (r !== 0) {
59
+ return r;
60
+ }
61
+ }
62
+ // prefix is the same, so go by length: shortest is first.
63
+ if (this.length < o.length) {
64
+ return -1;
65
+ } else if (this.length > o.length) {
66
+ return 1;
67
+ } else {
68
+ return 0;
69
+ }
70
+ }
71
+ toString(): string {
72
+ return this.map(v => v.value.value).join(' ');
73
+ }
74
+ };
@@ -0,0 +1,155 @@
1
+ //
2
+ // Version 1.0 of Keyman Developer Project .kpj file
3
+ //
4
+
5
+ import * as path from 'path';
6
+ import * as fs from 'fs';
7
+
8
+ export class KeymanDeveloperProject {
9
+ options: KeymanDeveloperProjectOptions;
10
+ files: KeymanDeveloperProjectFile[];
11
+ constructor(version: KeymanDeveloperProjectVersion) {
12
+ this.options = new KeymanDeveloperProjectOptions(version);
13
+ this.files = [];
14
+ }
15
+ /**
16
+ * Adds .kmn, .xml, .kps to project based on options.sourcePath
17
+ * @param projectPath Full path to project.kpj (even if the file doesn't exist)
18
+ */
19
+ populateFiles(projectPath: string) {
20
+ if(this.options.version != '2.0') {
21
+ throw new Error('populateFiles can only be called on a v2.0 project');
22
+ }
23
+
24
+ let sourcePath = this.resolveProjectPath(projectPath, this.options.sourcePath);
25
+ let files = fs.readdirSync(sourcePath);
26
+ for(let filename of files) {
27
+ let fullPath = path.join(sourcePath, filename);
28
+ if(filename.match(/\.xml$/i)) {
29
+ if(!fs.readFileSync(fullPath, 'utf-8').match(/ldmlKeyboard\.dtd/)) {
30
+ // Skip this .xml because we assume it isn't really a keyboard .xml
31
+ continue;
32
+ }
33
+ }
34
+ if(filename.match(/\.(kmn|kps|xml|model\.ts)$/i)) {
35
+ let file = new KeymanDeveloperProjectFile20(fullPath);
36
+ this.files.push(file);
37
+ }
38
+ }
39
+ }
40
+
41
+ resolveProjectPath(projectPath: string, p: string): string {
42
+ // Replace placeholders in the target path
43
+ return p.replace('$PROJECTPATH', path.dirname(projectPath));
44
+ }
45
+
46
+ resolveInputFilePath(projectPath: string, file: KeymanDeveloperProjectFile): string {
47
+ let p = path.dirname(projectPath);
48
+ return path.normalize(path.resolve(p, file.filePath));
49
+ }
50
+
51
+ resolveOutputFilePath(projectPath: string, file: KeymanDeveloperProjectFile, sourceExt: string, targetExt: string): string {
52
+ // Roughly corresponds to Delphi TProject.GetTargetFileName
53
+ let p = this.options.version == '1.0' ?
54
+ this.options.buildPath || '$SOURCEPATH' :
55
+ this.options.buildPath;
56
+
57
+ // Replace placeholders in the target path
58
+ if(this.options.version == '1.0') {
59
+ // TODO: do we need to support $VERSION?
60
+ // $SOURCEPATH only supported in 1.0 projects
61
+ p = p.replace('$SOURCEPATH', path.dirname(this.resolveInputFilePath(projectPath, file)));
62
+ }
63
+
64
+ p = this.resolveProjectPath(projectPath, p);
65
+
66
+ let f = file.filename.replace(new RegExp(`\\${sourceExt}$`, 'i'), targetExt);
67
+ return path.normalize(path.join(p, f));
68
+ }
69
+
70
+ };
71
+
72
+ export enum KeymanDeveloperProjectType {
73
+ Keyboard,
74
+ LexicalModel
75
+ };
76
+
77
+ export type KeymanDeveloperProjectVersion =
78
+ "1.0" | // Keyman Developer <17.0: All files referenced in .kpj
79
+ "2.0"; // Keyman Developer 17.0+: Files in sub-folders implicitly included
80
+
81
+ export class KeymanDeveloperProjectOptions {
82
+ buildPath: string;
83
+ sourcePath: string;
84
+ compilerWarningsAsErrors: boolean = false;
85
+ warnDeprecatedCode: boolean = true;
86
+ checkFilenameConventions: boolean = true;
87
+ projectType: KeymanDeveloperProjectType = KeymanDeveloperProjectType.Keyboard;
88
+ readonly version: KeymanDeveloperProjectVersion;
89
+ constructor(version: KeymanDeveloperProjectVersion) {
90
+ this.version = version;
91
+ switch(version) {
92
+ case "1.0":
93
+ this.buildPath = '';
94
+ this.sourcePath = '';
95
+ break;
96
+ case "2.0":
97
+ this.buildPath = '$PROJECTPATH/build';
98
+ this.sourcePath = '$PROJECTPATH/source';
99
+ break;
100
+ default:
101
+ throw new Error('Invalid version');
102
+ }
103
+ }
104
+ };
105
+
106
+ export type KeymanDeveloperProjectFile = KeymanDeveloperProjectFile10 | KeymanDeveloperProjectFile20;
107
+
108
+ export class KeymanDeveloperProjectFile10 {
109
+ readonly id: string; // 1.0 only
110
+ readonly filename: string;
111
+ readonly filePath: string;
112
+ readonly fileVersion: string; // 1.0 only
113
+ readonly fileType: string; // file extension of filename, but .model.ts is technically not the ext because of 2 periods
114
+ details: KeymanDeveloperProjectFileDetail_Kmn & KeymanDeveloperProjectFileDetail_Kps; // 1.0 only
115
+ childFiles: KeymanDeveloperProjectFile[]; // 1.0 only
116
+ constructor(id: string, filename: string, filePath: string, fileVersion:string, fileType: string) {
117
+ this.details = {};
118
+ this.childFiles = [];
119
+ this.id = id;
120
+ this.filename = filename;
121
+ this.filePath = filePath;
122
+ this.fileVersion = fileVersion;
123
+ this.fileType = fileType;
124
+ }
125
+ };
126
+
127
+ export type KeymanDeveloperProjectFileType20 = '.model.ts' | '.kmn' | '.xml' | '.kps';
128
+
129
+ export class KeymanDeveloperProjectFile20 {
130
+ readonly filename: string;
131
+ readonly filePath: string;
132
+ readonly fileType: string; // file extension of filename, but .model.ts is technically not the ext because of 2 periods
133
+ constructor(filePath: string) {
134
+ this.filename = path.basename(filePath);
135
+ this.filePath = filePath;
136
+ if(this.filename.match(/\.model\.ts$/)) {
137
+ // .model.ts is a bit of a hassle...
138
+ this.fileType = '.model.ts';
139
+ } else {
140
+ this.fileType = path.extname(this.filename);
141
+ }
142
+ }
143
+ };
144
+
145
+ export class KeymanDeveloperProjectFileDetail_Kps {
146
+ name?: string;
147
+ copyright?: string;
148
+ version?: string;
149
+ };
150
+
151
+ export class KeymanDeveloperProjectFileDetail_Kmn {
152
+ name?: string;
153
+ copyright?: string;
154
+ message?: string;
155
+ };
@@ -0,0 +1,103 @@
1
+ import * as xml2js from 'xml2js';
2
+ import { KPJFile, KPJFileProject } from './kpj-file.js';
3
+ import { default as AjvModule } from 'ajv';
4
+ const Ajv = AjvModule.default; // The actual expected Ajv type.
5
+ import { boxXmlArray } from '../util/util.js';
6
+ import { KeymanDeveloperProject, KeymanDeveloperProjectFile10, KeymanDeveloperProjectType } from './keyman-developer-project.js';
7
+
8
+ export class KPJFileReader {
9
+ public read(file: Uint8Array): KPJFile {
10
+ let data: KPJFile;
11
+
12
+ const parser = new xml2js.Parser({
13
+ explicitArray: false,
14
+ mergeAttrs: false,
15
+ includeWhiteChars: false,
16
+ normalize: false,
17
+ emptyTag: ''
18
+ });
19
+
20
+ parser.parseString(file, (e: unknown, r: unknown) => { data = r as KPJFile });
21
+ data = this.boxArrays(data);
22
+ return data as KPJFile;
23
+ }
24
+
25
+ public validate(source: KPJFile, schemaBuffer: Buffer): void {
26
+ const schema = JSON.parse(schemaBuffer.toString('utf8'));
27
+ const ajv = new Ajv();
28
+ if(!ajv.validate(schema, source)) {
29
+ throw new Error(ajv.errorsText());
30
+ }
31
+ }
32
+
33
+ private boolFromString(value: string, def: boolean) {
34
+ value = (value || '').toLowerCase();
35
+ if(value === 'true') return true;
36
+ if(value === 'false') return false;
37
+ return def;
38
+ }
39
+
40
+ public transform(projectPath: string, source: KPJFile): KeymanDeveloperProject {
41
+ // NOTE: at this point, the xml should have been validated
42
+ // and matched the schema result so we can assume the source
43
+ // is a valid shape
44
+ let project = source.KeymanDeveloperProject;
45
+ let result: KeymanDeveloperProject = new KeymanDeveloperProject(project.Options?.Version || "1.0");
46
+ if(result.options.version == '2.0') {
47
+ result.options.buildPath = (project.Options?.BuildPath || result.options.buildPath).replace(/\\/g, '/');
48
+ result.options.sourcePath = (project.Options?.SourcePath || result.options.sourcePath).replace(/\\/g, '/');
49
+ } else {
50
+ result.options.buildPath = (project.Options?.BuildPath || '').replace(/\\/g, '/');
51
+ }
52
+ result.options.checkFilenameConventions = this.boolFromString(project.Options?.CheckFilenameConventions, true);
53
+ result.options.compilerWarningsAsErrors = this.boolFromString(project.Options?.CompilerWarningsAsErrors, false);
54
+ result.options.warnDeprecatedCode = this.boolFromString(project.Options?.WarnDeprecatedCode, true);
55
+ result.options.projectType =
56
+ project.Options?.ProjectType == 'keyboard' ? KeymanDeveloperProjectType.Keyboard :
57
+ project.Options?.ProjectType == 'lexicalmodel' ? KeymanDeveloperProjectType.LexicalModel :
58
+ KeymanDeveloperProjectType.Keyboard; // Default is keyboard if missing
59
+
60
+ if(result.options.version == '1.0') {
61
+ this.transformFilesVersion10(project, result);
62
+ } else {
63
+ result.populateFiles(projectPath);
64
+ }
65
+
66
+ return result;
67
+ }
68
+
69
+ private transformFilesVersion10(project: KPJFileProject, result: KeymanDeveloperProject) {
70
+ let ids: { [id: string]: KeymanDeveloperProjectFile10; } = {};
71
+ for (let sourceFile of project.Files?.File) {
72
+ let file: KeymanDeveloperProjectFile10 = new KeymanDeveloperProjectFile10(
73
+ sourceFile.ID || '',
74
+ sourceFile.Filename || '',
75
+ (sourceFile.Filepath || '').replace(/\\/g, '/'),
76
+ sourceFile.FileVersion || '',
77
+ sourceFile.FileType || ''
78
+ );
79
+ if (sourceFile.Details) {
80
+ file.details.copyright = sourceFile.Details.Copyright;
81
+ file.details.name = sourceFile.Details.Name;
82
+ file.details.message = sourceFile.Details.Message;
83
+ file.details.version = sourceFile.Details.Version;
84
+ }
85
+ if (sourceFile.ParentFileID && ids[sourceFile.ParentFileID]) {
86
+ ids[sourceFile.ParentFileID].childFiles.push(file);
87
+ } else {
88
+ result.files.push(file);
89
+ ids[file.id] = file;
90
+ }
91
+ }
92
+ }
93
+
94
+ /**
95
+ * xml2js will not place single-entry objects into arrays.
96
+ * Easiest way to fix this is to box them ourselves as needed
97
+ * @param source KVKSourceFile
98
+ */
99
+ private boxArrays(source: KPJFile) {
100
+ boxXmlArray(source.KeymanDeveloperProject?.Files, 'File');
101
+ return source;
102
+ }
103
+ }