@keymanapp/kmc-package 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 (79) hide show
  1. package/.nyc_output/coverage-4892-1681239251006-0.json +1 -0
  2. package/Makefile +38 -0
  3. package/build/src/kmp-compiler.d.ts +18 -0
  4. package/build/src/kmp-compiler.d.ts.map +1 -0
  5. package/build/src/kmp-compiler.js +232 -0
  6. package/build/src/kmp-compiler.js.map +1 -0
  7. package/build/src/kmp-json-file.d.ts +68 -0
  8. package/build/src/kmp-json-file.d.ts.map +1 -0
  9. package/build/src/kmp-json-file.js +2 -0
  10. package/build/src/kmp-json-file.js.map +1 -0
  11. package/build/src/kps-file.d.ts +98 -0
  12. package/build/src/kps-file.d.ts.map +1 -0
  13. package/build/src/kps-file.js +16 -0
  14. package/build/src/kps-file.js.map +1 -0
  15. package/build/test/helpers/index.d.ts +10 -0
  16. package/build/test/helpers/index.d.ts.map +1 -0
  17. package/build/test/helpers/index.js +17 -0
  18. package/build/test/helpers/index.js.map +1 -0
  19. package/build/test/test-package-compiler.d.ts +2 -0
  20. package/build/test/test-package-compiler.d.ts.map +1 -0
  21. package/build/test/test-package-compiler.js +97 -0
  22. package/build/test/test-package-compiler.js.map +1 -0
  23. package/build/test/tsconfig.tsbuildinfo +1 -0
  24. package/build/tsconfig.tsbuildinfo +1 -0
  25. package/build.sh +66 -0
  26. package/coverage/lcov-report/base.css +224 -0
  27. package/coverage/lcov-report/block-navigation.js +87 -0
  28. package/coverage/lcov-report/favicon.png +0 -0
  29. package/coverage/lcov-report/index.html +146 -0
  30. package/coverage/lcov-report/prettify.css +1 -0
  31. package/coverage/lcov-report/prettify.js +2 -0
  32. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  33. package/coverage/lcov-report/sorter.js +196 -0
  34. package/coverage/lcov-report/src/index.html +116 -0
  35. package/coverage/lcov-report/src/kmp-compiler.ts.html +904 -0
  36. package/coverage/lcov-report/test/helpers/index.html +116 -0
  37. package/coverage/lcov-report/test/helpers/index.ts.html +136 -0
  38. package/coverage/lcov-report/test/index.html +116 -0
  39. package/coverage/lcov-report/test/test-package-compiler.ts.html +445 -0
  40. package/coverage/lcov.info +518 -0
  41. package/package.json +54 -0
  42. package/src/kmp-compiler.ts +273 -0
  43. package/src/kmp-json-file.ts +77 -0
  44. package/src/kps-file.ts +126 -0
  45. package/test/fixtures/example.qaa.sencoten/example.qaa.sencoten.model.js +55 -0
  46. package/test/fixtures/example.qaa.sencoten/example.qaa.sencoten.model.kmp.intermediate.json +48 -0
  47. package/test/fixtures/example.qaa.sencoten/example.qaa.sencoten.model.kmp.json +48 -0
  48. package/test/fixtures/example.qaa.sencoten/example.qaa.sencoten.model.kmp.zipped.json +45 -0
  49. package/test/fixtures/example.qaa.sencoten/example.qaa.sencoten.model.kps +35 -0
  50. package/test/fixtures/example.qaa.sencoten/example.qaa.sencoten.model.ts +6 -0
  51. package/test/fixtures/example.qaa.sencoten/wordlist.tsv +10 -0
  52. package/test/fixtures/khmer_angkor/build/khmer_angkor.js +1 -0
  53. package/test/fixtures/khmer_angkor/build/khmer_angkor.kmx +0 -0
  54. package/test/fixtures/khmer_angkor/build/khmer_angkor.kvk +0 -0
  55. package/test/fixtures/khmer_angkor/ref/kmp.json +110 -0
  56. package/test/fixtures/khmer_angkor/shared/fonts/khmer/busrakbd/khmer_busra_kbd.ttf +0 -0
  57. package/test/fixtures/khmer_angkor/shared/fonts/khmer/mondulkiri/FONTLOG.txt +123 -0
  58. package/test/fixtures/khmer_angkor/shared/fonts/khmer/mondulkiri/Mondulkiri-R.ttf +0 -0
  59. package/test/fixtures/khmer_angkor/shared/fonts/khmer/mondulkiri/OFL-FAQ.txt +425 -0
  60. package/test/fixtures/khmer_angkor/shared/fonts/khmer/mondulkiri/OFL.txt +95 -0
  61. package/test/fixtures/khmer_angkor/source/khmer_angkor.kps +131 -0
  62. package/test/fixtures/khmer_angkor/source/readme.htm +23 -0
  63. package/test/fixtures/khmer_angkor/source/splash.gif +0 -0
  64. package/test/fixtures/khmer_angkor/source/welcome/KAK_Documentation_EN.pdf +0 -0
  65. package/test/fixtures/khmer_angkor/source/welcome/KAK_Documentation_KH.pdf +0 -0
  66. package/test/fixtures/khmer_angkor/source/welcome/image002.png +0 -0
  67. package/test/fixtures/khmer_angkor/source/welcome/keyboard_layout.png +0 -0
  68. package/test/fixtures/khmer_angkor/source/welcome/welcome.htm +54 -0
  69. package/test/fixtures/withfolders.qaa.sencoten/build/withfolders.qaa.sencoten.model.js +55 -0
  70. package/test/fixtures/withfolders.qaa.sencoten/source/welcome.htm +1 -0
  71. package/test/fixtures/withfolders.qaa.sencoten/source/withfolders.qaa.sencoten.model.kps +41 -0
  72. package/test/fixtures/withfolders.qaa.sencoten/source/withfolders.qaa.sencoten.model.ts +6 -0
  73. package/test/fixtures/withfolders.qaa.sencoten/source/wordlist.tsv +10 -0
  74. package/test/fixtures/withfolders.qaa.sencoten/withfolders.qaa.sencoten.model.kmp.intermediate.json +52 -0
  75. package/test/fixtures/withfolders.qaa.sencoten/withfolders.qaa.sencoten.model.kmp.zipped.json +50 -0
  76. package/test/helpers/index.ts +17 -0
  77. package/test/test-package-compiler.ts +120 -0
  78. package/test/tsconfig.json +19 -0
  79. package/tsconfig.json +15 -0
@@ -0,0 +1,904 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for src/kmp-compiler.ts</title>
7
+ <meta charset="utf-8" />
8
+ <link rel="stylesheet" href="../prettify.css" />
9
+ <link rel="stylesheet" href="../base.css" />
10
+ <link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
11
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
12
+ <style type='text/css'>
13
+ .coverage-summary .sorter {
14
+ background-image: url(../sort-arrow-sprite.png);
15
+ }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <div class='wrapper'>
21
+ <div class='pad1'>
22
+ <h1><a href="../index.html">All files</a> / <a href="index.html">src</a> kmp-compiler.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">95.23% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>260/273</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">80% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>40/50</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">100% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>7/7</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">95.23% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>260/273</span>
50
+ </div>
51
+
52
+
53
+ </div>
54
+ <p class="quiet">
55
+ Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
+ </p>
57
+ <template id="filterTemplate">
58
+ <div class="quiet">
59
+ Filter:
60
+ <input oninput="onInput()" type="search" id="fileSearch">
61
+ </div>
62
+ </template>
63
+ </div>
64
+ <div class='status-line high'></div>
65
+ <pre><table class="coverage">
66
+ <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
+ <a name='L2'></a><a href='#L2'>2</a>
68
+ <a name='L3'></a><a href='#L3'>3</a>
69
+ <a name='L4'></a><a href='#L4'>4</a>
70
+ <a name='L5'></a><a href='#L5'>5</a>
71
+ <a name='L6'></a><a href='#L6'>6</a>
72
+ <a name='L7'></a><a href='#L7'>7</a>
73
+ <a name='L8'></a><a href='#L8'>8</a>
74
+ <a name='L9'></a><a href='#L9'>9</a>
75
+ <a name='L10'></a><a href='#L10'>10</a>
76
+ <a name='L11'></a><a href='#L11'>11</a>
77
+ <a name='L12'></a><a href='#L12'>12</a>
78
+ <a name='L13'></a><a href='#L13'>13</a>
79
+ <a name='L14'></a><a href='#L14'>14</a>
80
+ <a name='L15'></a><a href='#L15'>15</a>
81
+ <a name='L16'></a><a href='#L16'>16</a>
82
+ <a name='L17'></a><a href='#L17'>17</a>
83
+ <a name='L18'></a><a href='#L18'>18</a>
84
+ <a name='L19'></a><a href='#L19'>19</a>
85
+ <a name='L20'></a><a href='#L20'>20</a>
86
+ <a name='L21'></a><a href='#L21'>21</a>
87
+ <a name='L22'></a><a href='#L22'>22</a>
88
+ <a name='L23'></a><a href='#L23'>23</a>
89
+ <a name='L24'></a><a href='#L24'>24</a>
90
+ <a name='L25'></a><a href='#L25'>25</a>
91
+ <a name='L26'></a><a href='#L26'>26</a>
92
+ <a name='L27'></a><a href='#L27'>27</a>
93
+ <a name='L28'></a><a href='#L28'>28</a>
94
+ <a name='L29'></a><a href='#L29'>29</a>
95
+ <a name='L30'></a><a href='#L30'>30</a>
96
+ <a name='L31'></a><a href='#L31'>31</a>
97
+ <a name='L32'></a><a href='#L32'>32</a>
98
+ <a name='L33'></a><a href='#L33'>33</a>
99
+ <a name='L34'></a><a href='#L34'>34</a>
100
+ <a name='L35'></a><a href='#L35'>35</a>
101
+ <a name='L36'></a><a href='#L36'>36</a>
102
+ <a name='L37'></a><a href='#L37'>37</a>
103
+ <a name='L38'></a><a href='#L38'>38</a>
104
+ <a name='L39'></a><a href='#L39'>39</a>
105
+ <a name='L40'></a><a href='#L40'>40</a>
106
+ <a name='L41'></a><a href='#L41'>41</a>
107
+ <a name='L42'></a><a href='#L42'>42</a>
108
+ <a name='L43'></a><a href='#L43'>43</a>
109
+ <a name='L44'></a><a href='#L44'>44</a>
110
+ <a name='L45'></a><a href='#L45'>45</a>
111
+ <a name='L46'></a><a href='#L46'>46</a>
112
+ <a name='L47'></a><a href='#L47'>47</a>
113
+ <a name='L48'></a><a href='#L48'>48</a>
114
+ <a name='L49'></a><a href='#L49'>49</a>
115
+ <a name='L50'></a><a href='#L50'>50</a>
116
+ <a name='L51'></a><a href='#L51'>51</a>
117
+ <a name='L52'></a><a href='#L52'>52</a>
118
+ <a name='L53'></a><a href='#L53'>53</a>
119
+ <a name='L54'></a><a href='#L54'>54</a>
120
+ <a name='L55'></a><a href='#L55'>55</a>
121
+ <a name='L56'></a><a href='#L56'>56</a>
122
+ <a name='L57'></a><a href='#L57'>57</a>
123
+ <a name='L58'></a><a href='#L58'>58</a>
124
+ <a name='L59'></a><a href='#L59'>59</a>
125
+ <a name='L60'></a><a href='#L60'>60</a>
126
+ <a name='L61'></a><a href='#L61'>61</a>
127
+ <a name='L62'></a><a href='#L62'>62</a>
128
+ <a name='L63'></a><a href='#L63'>63</a>
129
+ <a name='L64'></a><a href='#L64'>64</a>
130
+ <a name='L65'></a><a href='#L65'>65</a>
131
+ <a name='L66'></a><a href='#L66'>66</a>
132
+ <a name='L67'></a><a href='#L67'>67</a>
133
+ <a name='L68'></a><a href='#L68'>68</a>
134
+ <a name='L69'></a><a href='#L69'>69</a>
135
+ <a name='L70'></a><a href='#L70'>70</a>
136
+ <a name='L71'></a><a href='#L71'>71</a>
137
+ <a name='L72'></a><a href='#L72'>72</a>
138
+ <a name='L73'></a><a href='#L73'>73</a>
139
+ <a name='L74'></a><a href='#L74'>74</a>
140
+ <a name='L75'></a><a href='#L75'>75</a>
141
+ <a name='L76'></a><a href='#L76'>76</a>
142
+ <a name='L77'></a><a href='#L77'>77</a>
143
+ <a name='L78'></a><a href='#L78'>78</a>
144
+ <a name='L79'></a><a href='#L79'>79</a>
145
+ <a name='L80'></a><a href='#L80'>80</a>
146
+ <a name='L81'></a><a href='#L81'>81</a>
147
+ <a name='L82'></a><a href='#L82'>82</a>
148
+ <a name='L83'></a><a href='#L83'>83</a>
149
+ <a name='L84'></a><a href='#L84'>84</a>
150
+ <a name='L85'></a><a href='#L85'>85</a>
151
+ <a name='L86'></a><a href='#L86'>86</a>
152
+ <a name='L87'></a><a href='#L87'>87</a>
153
+ <a name='L88'></a><a href='#L88'>88</a>
154
+ <a name='L89'></a><a href='#L89'>89</a>
155
+ <a name='L90'></a><a href='#L90'>90</a>
156
+ <a name='L91'></a><a href='#L91'>91</a>
157
+ <a name='L92'></a><a href='#L92'>92</a>
158
+ <a name='L93'></a><a href='#L93'>93</a>
159
+ <a name='L94'></a><a href='#L94'>94</a>
160
+ <a name='L95'></a><a href='#L95'>95</a>
161
+ <a name='L96'></a><a href='#L96'>96</a>
162
+ <a name='L97'></a><a href='#L97'>97</a>
163
+ <a name='L98'></a><a href='#L98'>98</a>
164
+ <a name='L99'></a><a href='#L99'>99</a>
165
+ <a name='L100'></a><a href='#L100'>100</a>
166
+ <a name='L101'></a><a href='#L101'>101</a>
167
+ <a name='L102'></a><a href='#L102'>102</a>
168
+ <a name='L103'></a><a href='#L103'>103</a>
169
+ <a name='L104'></a><a href='#L104'>104</a>
170
+ <a name='L105'></a><a href='#L105'>105</a>
171
+ <a name='L106'></a><a href='#L106'>106</a>
172
+ <a name='L107'></a><a href='#L107'>107</a>
173
+ <a name='L108'></a><a href='#L108'>108</a>
174
+ <a name='L109'></a><a href='#L109'>109</a>
175
+ <a name='L110'></a><a href='#L110'>110</a>
176
+ <a name='L111'></a><a href='#L111'>111</a>
177
+ <a name='L112'></a><a href='#L112'>112</a>
178
+ <a name='L113'></a><a href='#L113'>113</a>
179
+ <a name='L114'></a><a href='#L114'>114</a>
180
+ <a name='L115'></a><a href='#L115'>115</a>
181
+ <a name='L116'></a><a href='#L116'>116</a>
182
+ <a name='L117'></a><a href='#L117'>117</a>
183
+ <a name='L118'></a><a href='#L118'>118</a>
184
+ <a name='L119'></a><a href='#L119'>119</a>
185
+ <a name='L120'></a><a href='#L120'>120</a>
186
+ <a name='L121'></a><a href='#L121'>121</a>
187
+ <a name='L122'></a><a href='#L122'>122</a>
188
+ <a name='L123'></a><a href='#L123'>123</a>
189
+ <a name='L124'></a><a href='#L124'>124</a>
190
+ <a name='L125'></a><a href='#L125'>125</a>
191
+ <a name='L126'></a><a href='#L126'>126</a>
192
+ <a name='L127'></a><a href='#L127'>127</a>
193
+ <a name='L128'></a><a href='#L128'>128</a>
194
+ <a name='L129'></a><a href='#L129'>129</a>
195
+ <a name='L130'></a><a href='#L130'>130</a>
196
+ <a name='L131'></a><a href='#L131'>131</a>
197
+ <a name='L132'></a><a href='#L132'>132</a>
198
+ <a name='L133'></a><a href='#L133'>133</a>
199
+ <a name='L134'></a><a href='#L134'>134</a>
200
+ <a name='L135'></a><a href='#L135'>135</a>
201
+ <a name='L136'></a><a href='#L136'>136</a>
202
+ <a name='L137'></a><a href='#L137'>137</a>
203
+ <a name='L138'></a><a href='#L138'>138</a>
204
+ <a name='L139'></a><a href='#L139'>139</a>
205
+ <a name='L140'></a><a href='#L140'>140</a>
206
+ <a name='L141'></a><a href='#L141'>141</a>
207
+ <a name='L142'></a><a href='#L142'>142</a>
208
+ <a name='L143'></a><a href='#L143'>143</a>
209
+ <a name='L144'></a><a href='#L144'>144</a>
210
+ <a name='L145'></a><a href='#L145'>145</a>
211
+ <a name='L146'></a><a href='#L146'>146</a>
212
+ <a name='L147'></a><a href='#L147'>147</a>
213
+ <a name='L148'></a><a href='#L148'>148</a>
214
+ <a name='L149'></a><a href='#L149'>149</a>
215
+ <a name='L150'></a><a href='#L150'>150</a>
216
+ <a name='L151'></a><a href='#L151'>151</a>
217
+ <a name='L152'></a><a href='#L152'>152</a>
218
+ <a name='L153'></a><a href='#L153'>153</a>
219
+ <a name='L154'></a><a href='#L154'>154</a>
220
+ <a name='L155'></a><a href='#L155'>155</a>
221
+ <a name='L156'></a><a href='#L156'>156</a>
222
+ <a name='L157'></a><a href='#L157'>157</a>
223
+ <a name='L158'></a><a href='#L158'>158</a>
224
+ <a name='L159'></a><a href='#L159'>159</a>
225
+ <a name='L160'></a><a href='#L160'>160</a>
226
+ <a name='L161'></a><a href='#L161'>161</a>
227
+ <a name='L162'></a><a href='#L162'>162</a>
228
+ <a name='L163'></a><a href='#L163'>163</a>
229
+ <a name='L164'></a><a href='#L164'>164</a>
230
+ <a name='L165'></a><a href='#L165'>165</a>
231
+ <a name='L166'></a><a href='#L166'>166</a>
232
+ <a name='L167'></a><a href='#L167'>167</a>
233
+ <a name='L168'></a><a href='#L168'>168</a>
234
+ <a name='L169'></a><a href='#L169'>169</a>
235
+ <a name='L170'></a><a href='#L170'>170</a>
236
+ <a name='L171'></a><a href='#L171'>171</a>
237
+ <a name='L172'></a><a href='#L172'>172</a>
238
+ <a name='L173'></a><a href='#L173'>173</a>
239
+ <a name='L174'></a><a href='#L174'>174</a>
240
+ <a name='L175'></a><a href='#L175'>175</a>
241
+ <a name='L176'></a><a href='#L176'>176</a>
242
+ <a name='L177'></a><a href='#L177'>177</a>
243
+ <a name='L178'></a><a href='#L178'>178</a>
244
+ <a name='L179'></a><a href='#L179'>179</a>
245
+ <a name='L180'></a><a href='#L180'>180</a>
246
+ <a name='L181'></a><a href='#L181'>181</a>
247
+ <a name='L182'></a><a href='#L182'>182</a>
248
+ <a name='L183'></a><a href='#L183'>183</a>
249
+ <a name='L184'></a><a href='#L184'>184</a>
250
+ <a name='L185'></a><a href='#L185'>185</a>
251
+ <a name='L186'></a><a href='#L186'>186</a>
252
+ <a name='L187'></a><a href='#L187'>187</a>
253
+ <a name='L188'></a><a href='#L188'>188</a>
254
+ <a name='L189'></a><a href='#L189'>189</a>
255
+ <a name='L190'></a><a href='#L190'>190</a>
256
+ <a name='L191'></a><a href='#L191'>191</a>
257
+ <a name='L192'></a><a href='#L192'>192</a>
258
+ <a name='L193'></a><a href='#L193'>193</a>
259
+ <a name='L194'></a><a href='#L194'>194</a>
260
+ <a name='L195'></a><a href='#L195'>195</a>
261
+ <a name='L196'></a><a href='#L196'>196</a>
262
+ <a name='L197'></a><a href='#L197'>197</a>
263
+ <a name='L198'></a><a href='#L198'>198</a>
264
+ <a name='L199'></a><a href='#L199'>199</a>
265
+ <a name='L200'></a><a href='#L200'>200</a>
266
+ <a name='L201'></a><a href='#L201'>201</a>
267
+ <a name='L202'></a><a href='#L202'>202</a>
268
+ <a name='L203'></a><a href='#L203'>203</a>
269
+ <a name='L204'></a><a href='#L204'>204</a>
270
+ <a name='L205'></a><a href='#L205'>205</a>
271
+ <a name='L206'></a><a href='#L206'>206</a>
272
+ <a name='L207'></a><a href='#L207'>207</a>
273
+ <a name='L208'></a><a href='#L208'>208</a>
274
+ <a name='L209'></a><a href='#L209'>209</a>
275
+ <a name='L210'></a><a href='#L210'>210</a>
276
+ <a name='L211'></a><a href='#L211'>211</a>
277
+ <a name='L212'></a><a href='#L212'>212</a>
278
+ <a name='L213'></a><a href='#L213'>213</a>
279
+ <a name='L214'></a><a href='#L214'>214</a>
280
+ <a name='L215'></a><a href='#L215'>215</a>
281
+ <a name='L216'></a><a href='#L216'>216</a>
282
+ <a name='L217'></a><a href='#L217'>217</a>
283
+ <a name='L218'></a><a href='#L218'>218</a>
284
+ <a name='L219'></a><a href='#L219'>219</a>
285
+ <a name='L220'></a><a href='#L220'>220</a>
286
+ <a name='L221'></a><a href='#L221'>221</a>
287
+ <a name='L222'></a><a href='#L222'>222</a>
288
+ <a name='L223'></a><a href='#L223'>223</a>
289
+ <a name='L224'></a><a href='#L224'>224</a>
290
+ <a name='L225'></a><a href='#L225'>225</a>
291
+ <a name='L226'></a><a href='#L226'>226</a>
292
+ <a name='L227'></a><a href='#L227'>227</a>
293
+ <a name='L228'></a><a href='#L228'>228</a>
294
+ <a name='L229'></a><a href='#L229'>229</a>
295
+ <a name='L230'></a><a href='#L230'>230</a>
296
+ <a name='L231'></a><a href='#L231'>231</a>
297
+ <a name='L232'></a><a href='#L232'>232</a>
298
+ <a name='L233'></a><a href='#L233'>233</a>
299
+ <a name='L234'></a><a href='#L234'>234</a>
300
+ <a name='L235'></a><a href='#L235'>235</a>
301
+ <a name='L236'></a><a href='#L236'>236</a>
302
+ <a name='L237'></a><a href='#L237'>237</a>
303
+ <a name='L238'></a><a href='#L238'>238</a>
304
+ <a name='L239'></a><a href='#L239'>239</a>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
340
+ <span class="cline-any cline-yes">1x</span>
341
+ <span class="cline-any cline-yes">1x</span>
342
+ <span class="cline-any cline-yes">1x</span>
343
+ <span class="cline-any cline-yes">1x</span>
344
+ <span class="cline-any cline-yes">1x</span>
345
+ <span class="cline-any cline-yes">1x</span>
346
+ <span class="cline-any cline-yes">1x</span>
347
+ <span class="cline-any cline-yes">1x</span>
348
+ <span class="cline-any cline-yes">1x</span>
349
+ <span class="cline-any cline-yes">1x</span>
350
+ <span class="cline-any cline-yes">1x</span>
351
+ <span class="cline-any cline-yes">1x</span>
352
+ <span class="cline-any cline-yes">1x</span>
353
+ <span class="cline-any cline-yes">1x</span>
354
+ <span class="cline-any cline-yes">1x</span>
355
+ <span class="cline-any cline-yes">5x</span>
356
+ <span class="cline-any cline-yes">5x</span>
357
+ <span class="cline-any cline-yes">5x</span>
358
+ <span class="cline-any cline-yes">5x</span>
359
+ <span class="cline-any cline-yes">5x</span>
360
+ <span class="cline-any cline-yes">5x</span>
361
+ <span class="cline-any cline-yes">5x</span>
362
+ <span class="cline-any cline-yes">5x</span>
363
+ <span class="cline-any cline-yes">5x</span>
364
+ <span class="cline-any cline-yes">5x</span>
365
+ <span class="cline-any cline-yes">5x</span>
366
+ <span class="cline-any cline-yes">5x</span>
367
+ <span class="cline-any cline-yes">5x</span>
368
+ <span class="cline-any cline-yes">5x</span>
369
+ <span class="cline-any cline-yes">5x</span>
370
+ <span class="cline-any cline-yes">5x</span>
371
+ <span class="cline-any cline-yes">5x</span>
372
+ <span class="cline-any cline-yes">5x</span>
373
+ <span class="cline-any cline-yes">5x</span>
374
+ <span class="cline-any cline-yes">5x</span>
375
+ <span class="cline-any cline-yes">5x</span>
376
+ <span class="cline-any cline-yes">5x</span>
377
+ <span class="cline-any cline-yes">5x</span>
378
+ <span class="cline-any cline-yes">5x</span>
379
+ <span class="cline-any cline-yes">5x</span>
380
+ <span class="cline-any cline-yes">5x</span>
381
+ <span class="cline-any cline-yes">5x</span>
382
+ <span class="cline-any cline-yes">5x</span>
383
+ <span class="cline-any cline-yes">5x</span>
384
+ <span class="cline-any cline-yes">5x</span>
385
+ <span class="cline-any cline-yes">5x</span>
386
+ <span class="cline-any cline-yes">5x</span>
387
+ <span class="cline-any cline-yes">5x</span>
388
+ <span class="cline-any cline-yes">5x</span>
389
+ <span class="cline-any cline-yes">5x</span>
390
+ <span class="cline-any cline-yes">5x</span>
391
+ <span class="cline-any cline-yes">5x</span>
392
+ <span class="cline-any cline-yes">5x</span>
393
+ <span class="cline-any cline-yes">5x</span>
394
+ <span class="cline-any cline-yes">5x</span>
395
+ <span class="cline-any cline-yes">5x</span>
396
+ <span class="cline-any cline-yes">5x</span>
397
+ <span class="cline-any cline-yes">5x</span>
398
+ <span class="cline-any cline-yes">5x</span>
399
+ <span class="cline-any cline-yes">5x</span>
400
+ <span class="cline-any cline-yes">5x</span>
401
+ <span class="cline-any cline-yes">5x</span>
402
+ <span class="cline-any cline-yes">5x</span>
403
+ <span class="cline-any cline-yes">25x</span>
404
+ <span class="cline-any cline-yes">2x</span>
405
+ <span class="cline-any cline-yes">2x</span>
406
+ <span class="cline-any cline-yes">25x</span>
407
+ <span class="cline-any cline-yes">5x</span>
408
+ <span class="cline-any cline-yes">5x</span>
409
+ <span class="cline-any cline-yes">5x</span>
410
+ <span class="cline-any cline-yes">5x</span>
411
+ <span class="cline-any cline-yes">5x</span>
412
+ <span class="cline-any cline-yes">5x</span>
413
+ <span class="cline-any cline-yes">5x</span>
414
+ <span class="cline-any cline-yes">5x</span>
415
+ <span class="cline-any cline-yes">5x</span>
416
+ <span class="cline-any cline-yes">5x</span>
417
+ <span class="cline-any cline-yes">5x</span>
418
+ <span class="cline-any cline-yes">5x</span>
419
+ <span class="cline-any cline-yes">5x</span>
420
+ <span class="cline-any cline-yes">5x</span>
421
+ <span class="cline-any cline-yes">5x</span>
422
+ <span class="cline-any cline-yes">5x</span>
423
+ <span class="cline-any cline-yes">5x</span>
424
+ <span class="cline-any cline-yes">5x</span>
425
+ <span class="cline-any cline-yes">5x</span>
426
+ <span class="cline-any cline-yes">5x</span>
427
+ <span class="cline-any cline-yes">5x</span>
428
+ <span class="cline-any cline-yes">5x</span>
429
+ <span class="cline-any cline-yes">5x</span>
430
+ <span class="cline-any cline-yes">21x</span>
431
+ <span class="cline-any cline-yes">21x</span>
432
+ <span class="cline-any cline-yes">21x</span>
433
+ <span class="cline-any cline-yes">21x</span>
434
+ <span class="cline-any cline-yes">21x</span>
435
+ <span class="cline-any cline-yes">21x</span>
436
+ <span class="cline-any cline-yes">5x</span>
437
+ <span class="cline-any cline-yes">5x</span>
438
+ <span class="cline-any cline-yes">5x</span>
439
+ <span class="cline-any cline-yes">5x</span>
440
+ <span class="cline-any cline-yes">5x</span>
441
+ <span class="cline-any cline-yes">5x</span>
442
+ <span class="cline-any cline-yes">5x</span>
443
+ <span class="cline-any cline-yes">5x</span>
444
+ <span class="cline-any cline-yes">5x</span>
445
+ <span class="cline-any cline-yes">5x</span>
446
+ <span class="cline-any cline-yes">5x</span>
447
+ <span class="cline-any cline-yes">5x</span>
448
+ <span class="cline-any cline-yes">5x</span>
449
+ <span class="cline-any cline-yes">5x</span>
450
+ <span class="cline-any cline-yes">5x</span>
451
+ <span class="cline-any cline-yes">1x</span>
452
+ <span class="cline-any cline-yes">1x</span>
453
+ <span class="cline-any cline-yes">1x</span>
454
+ <span class="cline-any cline-yes">1x</span>
455
+ <span class="cline-any cline-yes">1x</span>
456
+ <span class="cline-any cline-yes">1x</span>
457
+ <span class="cline-any cline-yes">1x</span>
458
+ <span class="cline-any cline-yes">1x</span>
459
+ <span class="cline-any cline-yes">1x</span>
460
+ <span class="cline-any cline-yes">1x</span>
461
+ <span class="cline-any cline-yes">1x</span>
462
+ <span class="cline-any cline-yes">5x</span>
463
+ <span class="cline-any cline-yes">5x</span>
464
+ <span class="cline-any cline-yes">5x</span>
465
+ <span class="cline-any cline-yes">5x</span>
466
+ <span class="cline-any cline-yes">5x</span>
467
+ <span class="cline-any cline-yes">5x</span>
468
+ <span class="cline-any cline-yes">4x</span>
469
+ <span class="cline-any cline-yes">4x</span>
470
+ <span class="cline-any cline-yes">4x</span>
471
+ <span class="cline-any cline-yes">4x</span>
472
+ <span class="cline-any cline-yes">5x</span>
473
+ <span class="cline-any cline-yes">5x</span>
474
+ <span class="cline-any cline-yes">5x</span>
475
+ <span class="cline-any cline-yes">5x</span>
476
+ <span class="cline-any cline-yes">5x</span>
477
+ <span class="cline-any cline-yes">5x</span>
478
+ <span class="cline-any cline-no">&nbsp;</span>
479
+ <span class="cline-any cline-no">&nbsp;</span>
480
+ <span class="cline-any cline-no">&nbsp;</span>
481
+ <span class="cline-any cline-no">&nbsp;</span>
482
+ <span class="cline-any cline-no">&nbsp;</span>
483
+ <span class="cline-any cline-yes">5x</span>
484
+ <span class="cline-any cline-yes">5x</span>
485
+ <span class="cline-any cline-yes">5x</span>
486
+ <span class="cline-any cline-yes">5x</span>
487
+ <span class="cline-any cline-yes">5x</span>
488
+ <span class="cline-any cline-yes">5x</span>
489
+ <span class="cline-any cline-no">&nbsp;</span>
490
+ <span class="cline-any cline-no">&nbsp;</span>
491
+ <span class="cline-any cline-yes">5x</span>
492
+ <span class="cline-any cline-yes">5x</span>
493
+ <span class="cline-any cline-yes">5x</span>
494
+ <span class="cline-any cline-yes">5x</span>
495
+ <span class="cline-any cline-yes">5x</span>
496
+ <span class="cline-any cline-yes">1x</span>
497
+ <span class="cline-any cline-yes">1x</span>
498
+ <span class="cline-any cline-yes">1x</span>
499
+ <span class="cline-any cline-yes">1x</span>
500
+ <span class="cline-any cline-yes">5x</span>
501
+ <span class="cline-any cline-yes">5x</span>
502
+ <span class="cline-any cline-yes">5x</span>
503
+ <span class="cline-any cline-yes">5x</span>
504
+ <span class="cline-any cline-yes">5x</span>
505
+ <span class="cline-any cline-yes">5x</span>
506
+ <span class="cline-any cline-yes">5x</span>
507
+ <span class="cline-any cline-yes">5x</span>
508
+ <span class="cline-any cline-yes">5x</span>
509
+ <span class="cline-any cline-yes">5x</span>
510
+ <span class="cline-any cline-yes">5x</span>
511
+ <span class="cline-any cline-yes">25x</span>
512
+ <span class="cline-any cline-yes">21x</span>
513
+ <span class="cline-any cline-yes">21x</span>
514
+ <span class="cline-any cline-yes">21x</span>
515
+ <span class="cline-any cline-yes">25x</span>
516
+ <span class="cline-any cline-yes">5x</span>
517
+ <span class="cline-any cline-yes">5x</span>
518
+ <span class="cline-any cline-yes">1x</span>
519
+ <span class="cline-any cline-yes">1x</span>
520
+ <span class="cline-any cline-yes">1x</span>
521
+ <span class="cline-any cline-yes">16x</span>
522
+ <span class="cline-any cline-yes">7x</span>
523
+ <span class="cline-any cline-yes">7x</span>
524
+ <span class="cline-any cline-yes">9x</span>
525
+ <span class="cline-any cline-yes">1x</span>
526
+ <span class="cline-any cline-yes">1x</span>
527
+ <span class="cline-any cline-yes">1x</span>
528
+ <span class="cline-any cline-yes">5x</span>
529
+ <span class="cline-any cline-yes">1x</span>
530
+ <span class="cline-any cline-yes">1x</span>
531
+ <span class="cline-any cline-yes">1x</span>
532
+ <span class="cline-any cline-yes">5x</span>
533
+ <span class="cline-any cline-yes">5x</span>
534
+ <span class="cline-any cline-yes">5x</span>
535
+ <span class="cline-any cline-yes">5x</span>
536
+ <span class="cline-any cline-yes">4x</span>
537
+ <span class="cline-any cline-yes">4x</span>
538
+ <span class="cline-any cline-yes">4x</span>
539
+ <span class="cline-any cline-yes">4x</span>
540
+ <span class="cline-any cline-yes">4x</span>
541
+ <span class="cline-any cline-yes">1x</span>
542
+ <span class="cline-any cline-yes">5x</span>
543
+ <span class="cline-any cline-yes">5x</span>
544
+ <span class="cline-any cline-yes">1x</span>
545
+ <span class="cline-any cline-yes">1x</span>
546
+ <span class="cline-any cline-yes">96x</span>
547
+ <span class="cline-any cline-yes">234x</span>
548
+ <span class="cline-any cline-yes">21x</span>
549
+ <span class="cline-any cline-yes">234x</span>
550
+ <span class="cline-any cline-yes">91x</span>
551
+ <span class="cline-any cline-yes">91x</span>
552
+ <span class="cline-any cline-yes">234x</span>
553
+ <span class="cline-any cline-yes">96x</span>
554
+ <span class="cline-any cline-yes">96x</span>
555
+ <span class="cline-any cline-yes">1x</span>
556
+ <span class="cline-any cline-yes">1x</span>
557
+ <span class="cline-any cline-yes">1x</span>
558
+ <span class="cline-any cline-yes">1x</span>
559
+ <span class="cline-any cline-yes">1x</span>
560
+ <span class="cline-any cline-yes">1x</span>
561
+ <span class="cline-any cline-yes">1x</span>
562
+ <span class="cline-any cline-yes">1x</span>
563
+ <span class="cline-any cline-yes">3x</span>
564
+ <span class="cline-any cline-yes">3x</span>
565
+ <span class="cline-any cline-yes">3x</span>
566
+ <span class="cline-any cline-yes">3x</span>
567
+ <span class="cline-any cline-yes">3x</span>
568
+ <span class="cline-any cline-yes">3x</span>
569
+ <span class="cline-any cline-yes">3x</span>
570
+ <span class="cline-any cline-yes">3x</span>
571
+ <span class="cline-any cline-yes">3x</span>
572
+ <span class="cline-any cline-no">&nbsp;</span>
573
+ <span class="cline-any cline-no">&nbsp;</span>
574
+ <span class="cline-any cline-yes">3x</span>
575
+ <span class="cline-any cline-yes">3x</span>
576
+ <span class="cline-any cline-yes">21x</span>
577
+ <span class="cline-any cline-yes">21x</span>
578
+ <span class="cline-any cline-yes">21x</span>
579
+ <span class="cline-any cline-yes">21x</span>
580
+ <span class="cline-any cline-yes">21x</span>
581
+ <span class="cline-any cline-yes">3x</span>
582
+ <span class="cline-any cline-yes">3x</span>
583
+ <span class="cline-any cline-yes">18x</span>
584
+ <span class="cline-any cline-yes">21x</span>
585
+ <span class="cline-any cline-no">&nbsp;</span>
586
+ <span class="cline-any cline-no">&nbsp;</span>
587
+ <span class="cline-any cline-no">&nbsp;</span>
588
+ <span class="cline-any cline-yes">21x</span>
589
+ <span class="cline-any cline-yes">18x</span>
590
+ <span class="cline-any cline-yes">18x</span>
591
+ <span class="cline-any cline-yes">18x</span>
592
+ <span class="cline-any cline-no">&nbsp;</span>
593
+ <span class="cline-any cline-yes">18x</span>
594
+ <span class="cline-any cline-yes">18x</span>
595
+ <span class="cline-any cline-yes">18x</span>
596
+ <span class="cline-any cline-yes">18x</span>
597
+ <span class="cline-any cline-yes">18x</span>
598
+ <span class="cline-any cline-yes">18x</span>
599
+ <span class="cline-any cline-yes">18x</span>
600
+ <span class="cline-any cline-yes">18x</span>
601
+ <span class="cline-any cline-yes">18x</span>
602
+ <span class="cline-any cline-yes">18x</span>
603
+ <span class="cline-any cline-yes">18x</span>
604
+ <span class="cline-any cline-yes">3x</span>
605
+ <span class="cline-any cline-yes">3x</span>
606
+ <span class="cline-any cline-yes">3x</span>
607
+ <span class="cline-any cline-yes">3x</span>
608
+ <span class="cline-any cline-yes">3x</span>
609
+ <span class="cline-any cline-yes">3x</span>
610
+ <span class="cline-any cline-yes">3x</span>
611
+ <span class="cline-any cline-yes">1x</span>
612
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import * as fs from 'fs';
613
+ import * as path from 'path';
614
+ import * as xml2js from 'xml2js';
615
+ import JSZip from 'jszip';
616
+ import KEYMAN_VERSION from "@keymanapp/keyman-version";
617
+ &nbsp;
618
+ import type { KpsFile, KpsFileContentFile, KpsFileInfo, KpsFileKeyboard, KpsFileLanguage, KpsFileLexicalModel, KpsFileOptions, KpsPackage } from './kps-file.js';
619
+ import type { KmpJsonFile, KmpJsonFileInfo, KmpJsonFileLanguage, KmpJsonFileOptions } from './kmp-json-file.js';
620
+ &nbsp;
621
+ export { type KmpJsonFile } from './kmp-json-file.js';
622
+ &nbsp;
623
+ const FILEVERSION_KMP_JSON = '12.0';
624
+ &nbsp;
625
+ export default class KmpCompiler {
626
+ &nbsp;
627
+ public transformKpsToKmpObject(kpsString: string, kpsPath: string): KmpJsonFile {
628
+ &nbsp;
629
+ // Load the KPS data from XML as JS structured data.
630
+ &nbsp;
631
+ let kpsPackage = (() =&gt; {
632
+ let a: KpsPackage;
633
+ let parser = new xml2js.Parser({
634
+ tagNameProcessors: [xml2js.processors.firstCharLowerCase],
635
+ explicitArray: false
636
+ });
637
+ parser.parseString(kpsString, (e: unknown, r: unknown) =&gt; { a = r as KpsPackage });
638
+ return a;
639
+ })();
640
+ &nbsp;
641
+ let kps: KpsFile = kpsPackage.package;
642
+ &nbsp;
643
+ //
644
+ // To convert to kmp.json, we need to:
645
+ //
646
+ // 1. Unwrap arrays (and convert to array where single object)
647
+ // 2. Fix casing on `iD`
648
+ // 3. Rewrap info, keyboard.languages, lexicalModel.languages, startMenu.items elements
649
+ // 4. Remove options.followKeyboardVersion, file.fileType
650
+ // 5. Convert file.copyLocation to a Number
651
+ // 6. Filenames need to be basenames (but this comes after processing)
652
+ //
653
+ &nbsp;
654
+ // Start to construct the kmp.json file from the .kps file
655
+ &nbsp;
656
+ let kmp: KmpJsonFile = {
657
+ system: {
658
+ fileVersion: FILEVERSION_KMP_JSON,
659
+ keymanDeveloperVersion: KEYMAN_VERSION.VERSION
660
+ },
661
+ options: {}
662
+ };
663
+ &nbsp;
664
+ //
665
+ // Fill in additional fields
666
+ //
667
+ &nbsp;
668
+ let keys: [keyof KpsFileOptions, keyof KmpJsonFileOptions][] = [
669
+ ['executeProgram','executeProgram'],
670
+ ['graphicFile', 'graphicFile'],
671
+ ['msiFileName','msiFilename'],
672
+ ['msiOptions', 'msiOptions'],
673
+ ['readMeFile', 'readmeFile']
674
+ ];
675
+ for (let [src,dst] of keys) {
676
+ if (kps.options[src]) {
677
+ kmp.options[dst] = kps.options[src];
678
+ }
679
+ }
680
+ &nbsp;
681
+ //
682
+ // Add basic metadata
683
+ //
684
+ &nbsp;
685
+ if(kps.info) {
686
+ kmp.info = this.kpsInfoToKmpInfo(kps.info);
687
+ }
688
+ &nbsp;
689
+ // FollowKeyboardVersion support
690
+ &nbsp;
691
+ if(kps.options?.followKeyboardVersion !== undefined) {
692
+ kmp.info.version = {
693
+ description: this.extractKeyboardVersionFromKmx(kpsPath, kps)
694
+ };
695
+ }
696
+ &nbsp;
697
+ //
698
+ // Add file metadata
699
+ //
700
+ &nbsp;
701
+ if(kps.files &amp;&amp; kps.files.file) {
702
+ kmp.files = this.arrayWrap(kps.files.file).map((file: KpsFileContentFile) =&gt; {
703
+ return {
704
+ name: file.name,
705
+ description: file.description,
706
+ copyLocation: parseInt(file.copyLocation, 10) || undefined
707
+ // note: we don't emit fileType as that is not permitted in kmp.json
708
+ };
709
+ });
710
+ }
711
+ kmp.files = kmp.files<span class="branch-0 cbranch-no" title="branch not covered" > ?? [];</span>
712
+ &nbsp;
713
+ // Add the standard kmp.json self-referential to match existing implementations
714
+ kmp.files.push({
715
+ name: "kmp.json",
716
+ description: "Package information (JSON)"
717
+ });
718
+ &nbsp;
719
+ //
720
+ // Add keyboard metadata
721
+ //
722
+ &nbsp;
723
+ if(kps.keyboards &amp;&amp; kps.keyboards.keyboard) {
724
+ kmp.keyboards = this.arrayWrap(kps.keyboards.keyboard).map((keyboard: KpsFileKeyboard) =&gt; {
725
+ return {
726
+ displayFont: keyboard.displayFont ? path.basename(keyboard.displayFont.replaceAll('\\', '/')) <span class="branch-0 cbranch-no" title="branch not covered" >: undefined,</span>
727
+ oskFont: keyboard.oSKFont ? path.basename(keyboard.oSKFont.replaceAll('\\', '/')) <span class="branch-0 cbranch-no" title="branch not covered" >: undefined,</span>
728
+ name:keyboard.name,
729
+ id:keyboard.iD,
730
+ version:keyboard.version,
731
+ languages: this.kpsLanguagesToKmpLanguages(this.arrayWrap(keyboard.languages.language) as KpsFileLanguage[])
732
+ };
733
+ });
734
+ }
735
+ &nbsp;
736
+ //
737
+ // Add lexical-model metadata
738
+ //
739
+ &nbsp;
740
+ if(kps.lexicalModels &amp;&amp; kps.lexicalModels.lexicalModel) {
741
+ kmp.lexicalModels = this.arrayWrap(kps.lexicalModels.lexicalModel).map((model: KpsFileLexicalModel) =&gt; {
742
+ return { name:model.name, id:model.iD, languages: this.kpsLanguagesToKmpLanguages(this.arrayWrap(model.languages.language) as KpsFileLanguage[]) }
743
+ });
744
+ }
745
+ &nbsp;
746
+ //
747
+ // Add Windows Start Menu metadata
748
+ //
749
+ &nbsp;
750
+ if(kps.startMenu &amp;&amp; kps.startMenu.items) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
751
+ <span class="cstat-no" title="statement not covered" > kmp.startMenu = {};</span>
752
+ <span class="cstat-no" title="statement not covered" > if(kps.startMenu.addUninstallEntry) kmp.startMenu.addUninstallEntry = kps.startMenu.addUninstallEntry === '';</span>
753
+ <span class="cstat-no" title="statement not covered" > if(kps.startMenu.folder) kmp.startMenu.folder = kps.startMenu.folder;</span>
754
+ <span class="cstat-no" title="statement not covered" > if(kps.startMenu.items &amp;&amp; kps.startMenu.items.item) kmp.startMenu.items = this.arrayWrap(kps.startMenu.items.item);</span>
755
+ <span class="cstat-no" title="statement not covered" > }</span>
756
+ &nbsp;
757
+ //
758
+ // Add translation strings
759
+ //
760
+ &nbsp;
761
+ if(kps.strings<span class="branch-0 cbranch-no" title="branch not covered" > &amp;&amp; kps.strings.string)</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
762
+ <span class="cstat-no" title="statement not covered" > kmp.strings = this.arrayWrap(kps.strings.string);</span>
763
+ <span class="cstat-no" title="statement not covered" > }</span>
764
+ &nbsp;
765
+ kmp = this.stripUndefined(kmp) as KmpJsonFile;
766
+ &nbsp;
767
+ return kmp;
768
+ }
769
+ &nbsp;
770
+ // Helper functions
771
+ &nbsp;
772
+ private kpsInfoToKmpInfo(info: KpsFileInfo): KmpJsonFileInfo {
773
+ let ni: KmpJsonFileInfo = {};
774
+ &nbsp;
775
+ const keys: [(keyof KpsFileInfo), (keyof KmpJsonFileInfo)][] = [
776
+ ['author','author'],
777
+ ['copyright','copyright'],
778
+ ['name','name'],
779
+ ['version','version'],
780
+ ['webSite','website']
781
+ ];
782
+ &nbsp;
783
+ for (let [src,dst] of keys) {
784
+ if (info[src]) {
785
+ ni[dst] = {description: info[src]._ ?? (typeof info[src] == 'string' ? info[src].toString() : '')};
786
+ if(info[src].$ &amp;&amp; info[src].$.URL) ni[dst].url = info[src].$.URL;
787
+ }
788
+ }
789
+ &nbsp;
790
+ return ni;
791
+ };
792
+ &nbsp;
793
+ private arrayWrap(a: unknown) {
794
+ if (Array.isArray(a)) {
795
+ return a;
796
+ }
797
+ return [a];
798
+ };
799
+ &nbsp;
800
+ private kpsLanguagesToKmpLanguages(language: KpsFileLanguage[]): KmpJsonFileLanguage[] {
801
+ return language.map((element) =&gt; { return { name: element._, id: element.$.ID } });
802
+ };
803
+ &nbsp;
804
+ private extractKeyboardVersionFromKmx(kpsPath: string, kps: KpsFile) {
805
+ // TODO-LDML: #7340 this is incomplete; we need to read from first .kmx
806
+ // When we do this, we'll need to update fixtures to have the correct
807
+ // version string also
808
+ if(!kps.keyboards || !kps.keyboards.keyboard) {
809
+ // We don't read from the kps metadata because we want the keyboard
810
+ // version data here;
811
+ // TODO: currently model files don't support follow-version?
812
+ return '0.0.0';
813
+ }
814
+ let k: KpsFileKeyboard[] = this.arrayWrap(kps.keyboards.keyboard);
815
+ return k?.[0]?.version<span class="branch-0 cbranch-no" title="branch not covered" > ?? '0.0.0';</span>
816
+ }
817
+ &nbsp;
818
+ private stripUndefined(o: any) {
819
+ for(const key in o) {
820
+ if(o[key] === undefined) {
821
+ delete o[key];
822
+ } else if(typeof o[key] == 'object') {
823
+ o[key] = this.stripUndefined(o[key]);
824
+ }
825
+ }
826
+ return o;
827
+ }
828
+ &nbsp;
829
+ /**
830
+ * Returns a Promise to the serialized data which can then be written to a .kmp file.
831
+ *
832
+ * @param kpsFilename - Filename of the kps, not read, used only for calculating relative paths
833
+ * @param kmpJsonData - The kmp.json Object
834
+ */
835
+ public buildKmpFile(kpsFilename: string, kmpJsonData: KmpJsonFile): Promise&lt;string&gt; {
836
+ const zip = JSZip();
837
+ &nbsp;
838
+ const kmpJsonFileName = 'kmp.json';
839
+ &nbsp;
840
+ const basePath = path.dirname(kpsFilename);
841
+ &nbsp;
842
+ // Make a copy of kmpJsonData, as we mutate paths for writing
843
+ const data: KmpJsonFile = JSON.parse(JSON.stringify(kmpJsonData));
844
+ if(!data.files) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
845
+ <span class="cstat-no" title="statement not covered" > data.files = [];</span>
846
+ <span class="cstat-no" title="statement not covered" > }</span>
847
+ &nbsp;
848
+ data.files.forEach(function(value) {
849
+ // Get the path of the file
850
+ let filename = value.name;
851
+ &nbsp;
852
+ // We add this separately after zipping all other files
853
+ if(filename == 'kmp.json') {
854
+ return;
855
+ }
856
+ &nbsp;
857
+ if(path.isAbsolute(value.name)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
858
+ <span class="cstat-no" title="statement not covered" > // absolute paths are not very cross-platform compatible -- we are going to have trouble</span>
859
+ <span class="cstat-no" title="statement not covered" > // with path separators and roots</span>
860
+ <span class="cstat-no" title="statement not covered" > // TODO: emit a warning</span>
861
+ } else {
862
+ // Transform separators to platform separators -- kps files may use
863
+ // either / or \, although older kps files were always \.
864
+ if(path.sep == '/') <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
865
+ <span class="cstat-no" title="statement not covered" > filename = filename.replace(/\\/g, '/');</span>
866
+ } else {
867
+ filename = filename.replace(/\//g, '\\');
868
+ }
869
+ filename = path.resolve(basePath, filename);
870
+ }
871
+ const basename = path.basename(filename);
872
+ let data = fs.readFileSync(filename);
873
+ zip.file(basename, data);
874
+ &nbsp;
875
+ // Remove path data from files before JSON save
876
+ value.name = basename;
877
+ });
878
+ &nbsp;
879
+ zip.file(kmpJsonFileName, JSON.stringify(data, null, 2));
880
+ &nbsp;
881
+ // Generate kmp file
882
+ return zip.generateAsync({type: 'binarystring', compression:'DEFLATE'});
883
+ }
884
+ }
885
+ &nbsp;</pre></td></tr></table></pre>
886
+
887
+ <div class='push'></div><!-- for sticky footer -->
888
+ </div><!-- /wrapper -->
889
+ <div class='footer quiet pad2 space-top1 center small'>
890
+ Code coverage generated by
891
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
892
+ at 2023-04-11T18:54:11.227Z
893
+ </div>
894
+ <script src="../prettify.js"></script>
895
+ <script>
896
+ window.onload = function () {
897
+ prettyPrint();
898
+ };
899
+ </script>
900
+ <script src="../sorter.js"></script>
901
+ <script src="../block-navigation.js"></script>
902
+ </body>
903
+ </html>
904
+