@flourish/sdk 5.2.2 → 5.2.4

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 (55) hide show
  1. package/.c8rc +4 -0
  2. package/RELEASE_NOTES.md +12 -0
  3. package/common/embed/credit.js +26 -11
  4. package/common/embed/embedding.js +1 -1
  5. package/common/embed/localizations.d.ts +46 -2
  6. package/common/embed/localizations.js +48 -37
  7. package/common/package.json +2 -2
  8. package/common/tsconfig.sdk.tsbuildinfo +1 -1
  9. package/common/utils/data.d.ts +2 -2
  10. package/common/utils/data.js +2 -1
  11. package/common/utils/types.d.ts +1 -2
  12. package/coverage-sdk/lcov-report/base.css +224 -0
  13. package/coverage-sdk/lcov-report/block-navigation.js +87 -0
  14. package/coverage-sdk/lcov-report/common/utils/columns.js.html +646 -0
  15. package/coverage-sdk/lcov-report/common/utils/index.html +131 -0
  16. package/coverage-sdk/lcov-report/common/utils/state.js.html +559 -0
  17. package/coverage-sdk/lcov-report/favicon.png +0 -0
  18. package/coverage-sdk/lcov-report/index.html +146 -0
  19. package/coverage-sdk/lcov-report/lib/common.js.html +181 -0
  20. package/coverage-sdk/lcov-report/lib/index.html +161 -0
  21. package/coverage-sdk/lcov-report/lib/log.js.html +178 -0
  22. package/coverage-sdk/lcov-report/lib/sdk.js.html +2008 -0
  23. package/coverage-sdk/lcov-report/lib/validate_config.js.html +1459 -0
  24. package/coverage-sdk/lcov-report/prettify.css +1 -0
  25. package/coverage-sdk/lcov-report/prettify.js +2 -0
  26. package/coverage-sdk/lcov-report/sort-arrow-sprite.png +0 -0
  27. package/coverage-sdk/lcov-report/sorter.js +210 -0
  28. package/coverage-sdk/lcov-report/test/lib/index.html +131 -0
  29. package/coverage-sdk/lcov-report/test/lib/sdk.js.html +532 -0
  30. package/coverage-sdk/lcov-report/test/lib/validate_config.js.html +3307 -0
  31. package/coverage-sdk/lcov.info +3556 -0
  32. package/coverage-sdk/tmp/coverage-36833-1757890375186-0.json +1 -0
  33. package/coverage-sdk/tmp/coverage-36834-1757890374890-0.json +1 -0
  34. package/lib/cmd/publish.js +1 -0
  35. package/lib/validate_config.js +31 -0
  36. package/package.json +7 -6
  37. package/server/columns.js +150 -0
  38. package/server/comms_js.js +13 -0
  39. package/server/data.js +132 -0
  40. package/server/json.js +40 -0
  41. package/server/views/index.html +13 -29
  42. package/site/embedded.js +2 -2
  43. package/site/images/embed_flourish_in_canva.png +0 -0
  44. package/site/images/flourish_app_icon.png +0 -0
  45. package/site/images/icon-arrow-down.svg +3 -0
  46. package/site/images/icon-arrow-left.svg +3 -0
  47. package/site/images/icon-close.svg +3 -0
  48. package/site/images/icon-login.svg +4 -0
  49. package/site/images/icon-sso.svg +4 -0
  50. package/site/images/share_image.jpg +0 -0
  51. package/site/images/upsell-presenter.jpg +0 -0
  52. package/site/images/upsell-publisher.jpg +0 -0
  53. package/site/script.js +3 -3
  54. package/site/sdk.css +1 -1
  55. package/test/lib/validate_config.js +126 -0
@@ -0,0 +1,1459 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for lib/validate_config.js</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">lib</a> validate_config.js</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">85.58% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>392/458</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">89.25% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>241/270</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">85% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>17/20</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">85.58% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>392/458</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 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>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a>
351
+ <a name='L286'></a><a href='#L286'>286</a>
352
+ <a name='L287'></a><a href='#L287'>287</a>
353
+ <a name='L288'></a><a href='#L288'>288</a>
354
+ <a name='L289'></a><a href='#L289'>289</a>
355
+ <a name='L290'></a><a href='#L290'>290</a>
356
+ <a name='L291'></a><a href='#L291'>291</a>
357
+ <a name='L292'></a><a href='#L292'>292</a>
358
+ <a name='L293'></a><a href='#L293'>293</a>
359
+ <a name='L294'></a><a href='#L294'>294</a>
360
+ <a name='L295'></a><a href='#L295'>295</a>
361
+ <a name='L296'></a><a href='#L296'>296</a>
362
+ <a name='L297'></a><a href='#L297'>297</a>
363
+ <a name='L298'></a><a href='#L298'>298</a>
364
+ <a name='L299'></a><a href='#L299'>299</a>
365
+ <a name='L300'></a><a href='#L300'>300</a>
366
+ <a name='L301'></a><a href='#L301'>301</a>
367
+ <a name='L302'></a><a href='#L302'>302</a>
368
+ <a name='L303'></a><a href='#L303'>303</a>
369
+ <a name='L304'></a><a href='#L304'>304</a>
370
+ <a name='L305'></a><a href='#L305'>305</a>
371
+ <a name='L306'></a><a href='#L306'>306</a>
372
+ <a name='L307'></a><a href='#L307'>307</a>
373
+ <a name='L308'></a><a href='#L308'>308</a>
374
+ <a name='L309'></a><a href='#L309'>309</a>
375
+ <a name='L310'></a><a href='#L310'>310</a>
376
+ <a name='L311'></a><a href='#L311'>311</a>
377
+ <a name='L312'></a><a href='#L312'>312</a>
378
+ <a name='L313'></a><a href='#L313'>313</a>
379
+ <a name='L314'></a><a href='#L314'>314</a>
380
+ <a name='L315'></a><a href='#L315'>315</a>
381
+ <a name='L316'></a><a href='#L316'>316</a>
382
+ <a name='L317'></a><a href='#L317'>317</a>
383
+ <a name='L318'></a><a href='#L318'>318</a>
384
+ <a name='L319'></a><a href='#L319'>319</a>
385
+ <a name='L320'></a><a href='#L320'>320</a>
386
+ <a name='L321'></a><a href='#L321'>321</a>
387
+ <a name='L322'></a><a href='#L322'>322</a>
388
+ <a name='L323'></a><a href='#L323'>323</a>
389
+ <a name='L324'></a><a href='#L324'>324</a>
390
+ <a name='L325'></a><a href='#L325'>325</a>
391
+ <a name='L326'></a><a href='#L326'>326</a>
392
+ <a name='L327'></a><a href='#L327'>327</a>
393
+ <a name='L328'></a><a href='#L328'>328</a>
394
+ <a name='L329'></a><a href='#L329'>329</a>
395
+ <a name='L330'></a><a href='#L330'>330</a>
396
+ <a name='L331'></a><a href='#L331'>331</a>
397
+ <a name='L332'></a><a href='#L332'>332</a>
398
+ <a name='L333'></a><a href='#L333'>333</a>
399
+ <a name='L334'></a><a href='#L334'>334</a>
400
+ <a name='L335'></a><a href='#L335'>335</a>
401
+ <a name='L336'></a><a href='#L336'>336</a>
402
+ <a name='L337'></a><a href='#L337'>337</a>
403
+ <a name='L338'></a><a href='#L338'>338</a>
404
+ <a name='L339'></a><a href='#L339'>339</a>
405
+ <a name='L340'></a><a href='#L340'>340</a>
406
+ <a name='L341'></a><a href='#L341'>341</a>
407
+ <a name='L342'></a><a href='#L342'>342</a>
408
+ <a name='L343'></a><a href='#L343'>343</a>
409
+ <a name='L344'></a><a href='#L344'>344</a>
410
+ <a name='L345'></a><a href='#L345'>345</a>
411
+ <a name='L346'></a><a href='#L346'>346</a>
412
+ <a name='L347'></a><a href='#L347'>347</a>
413
+ <a name='L348'></a><a href='#L348'>348</a>
414
+ <a name='L349'></a><a href='#L349'>349</a>
415
+ <a name='L350'></a><a href='#L350'>350</a>
416
+ <a name='L351'></a><a href='#L351'>351</a>
417
+ <a name='L352'></a><a href='#L352'>352</a>
418
+ <a name='L353'></a><a href='#L353'>353</a>
419
+ <a name='L354'></a><a href='#L354'>354</a>
420
+ <a name='L355'></a><a href='#L355'>355</a>
421
+ <a name='L356'></a><a href='#L356'>356</a>
422
+ <a name='L357'></a><a href='#L357'>357</a>
423
+ <a name='L358'></a><a href='#L358'>358</a>
424
+ <a name='L359'></a><a href='#L359'>359</a>
425
+ <a name='L360'></a><a href='#L360'>360</a>
426
+ <a name='L361'></a><a href='#L361'>361</a>
427
+ <a name='L362'></a><a href='#L362'>362</a>
428
+ <a name='L363'></a><a href='#L363'>363</a>
429
+ <a name='L364'></a><a href='#L364'>364</a>
430
+ <a name='L365'></a><a href='#L365'>365</a>
431
+ <a name='L366'></a><a href='#L366'>366</a>
432
+ <a name='L367'></a><a href='#L367'>367</a>
433
+ <a name='L368'></a><a href='#L368'>368</a>
434
+ <a name='L369'></a><a href='#L369'>369</a>
435
+ <a name='L370'></a><a href='#L370'>370</a>
436
+ <a name='L371'></a><a href='#L371'>371</a>
437
+ <a name='L372'></a><a href='#L372'>372</a>
438
+ <a name='L373'></a><a href='#L373'>373</a>
439
+ <a name='L374'></a><a href='#L374'>374</a>
440
+ <a name='L375'></a><a href='#L375'>375</a>
441
+ <a name='L376'></a><a href='#L376'>376</a>
442
+ <a name='L377'></a><a href='#L377'>377</a>
443
+ <a name='L378'></a><a href='#L378'>378</a>
444
+ <a name='L379'></a><a href='#L379'>379</a>
445
+ <a name='L380'></a><a href='#L380'>380</a>
446
+ <a name='L381'></a><a href='#L381'>381</a>
447
+ <a name='L382'></a><a href='#L382'>382</a>
448
+ <a name='L383'></a><a href='#L383'>383</a>
449
+ <a name='L384'></a><a href='#L384'>384</a>
450
+ <a name='L385'></a><a href='#L385'>385</a>
451
+ <a name='L386'></a><a href='#L386'>386</a>
452
+ <a name='L387'></a><a href='#L387'>387</a>
453
+ <a name='L388'></a><a href='#L388'>388</a>
454
+ <a name='L389'></a><a href='#L389'>389</a>
455
+ <a name='L390'></a><a href='#L390'>390</a>
456
+ <a name='L391'></a><a href='#L391'>391</a>
457
+ <a name='L392'></a><a href='#L392'>392</a>
458
+ <a name='L393'></a><a href='#L393'>393</a>
459
+ <a name='L394'></a><a href='#L394'>394</a>
460
+ <a name='L395'></a><a href='#L395'>395</a>
461
+ <a name='L396'></a><a href='#L396'>396</a>
462
+ <a name='L397'></a><a href='#L397'>397</a>
463
+ <a name='L398'></a><a href='#L398'>398</a>
464
+ <a name='L399'></a><a href='#L399'>399</a>
465
+ <a name='L400'></a><a href='#L400'>400</a>
466
+ <a name='L401'></a><a href='#L401'>401</a>
467
+ <a name='L402'></a><a href='#L402'>402</a>
468
+ <a name='L403'></a><a href='#L403'>403</a>
469
+ <a name='L404'></a><a href='#L404'>404</a>
470
+ <a name='L405'></a><a href='#L405'>405</a>
471
+ <a name='L406'></a><a href='#L406'>406</a>
472
+ <a name='L407'></a><a href='#L407'>407</a>
473
+ <a name='L408'></a><a href='#L408'>408</a>
474
+ <a name='L409'></a><a href='#L409'>409</a>
475
+ <a name='L410'></a><a href='#L410'>410</a>
476
+ <a name='L411'></a><a href='#L411'>411</a>
477
+ <a name='L412'></a><a href='#L412'>412</a>
478
+ <a name='L413'></a><a href='#L413'>413</a>
479
+ <a name='L414'></a><a href='#L414'>414</a>
480
+ <a name='L415'></a><a href='#L415'>415</a>
481
+ <a name='L416'></a><a href='#L416'>416</a>
482
+ <a name='L417'></a><a href='#L417'>417</a>
483
+ <a name='L418'></a><a href='#L418'>418</a>
484
+ <a name='L419'></a><a href='#L419'>419</a>
485
+ <a name='L420'></a><a href='#L420'>420</a>
486
+ <a name='L421'></a><a href='#L421'>421</a>
487
+ <a name='L422'></a><a href='#L422'>422</a>
488
+ <a name='L423'></a><a href='#L423'>423</a>
489
+ <a name='L424'></a><a href='#L424'>424</a>
490
+ <a name='L425'></a><a href='#L425'>425</a>
491
+ <a name='L426'></a><a href='#L426'>426</a>
492
+ <a name='L427'></a><a href='#L427'>427</a>
493
+ <a name='L428'></a><a href='#L428'>428</a>
494
+ <a name='L429'></a><a href='#L429'>429</a>
495
+ <a name='L430'></a><a href='#L430'>430</a>
496
+ <a name='L431'></a><a href='#L431'>431</a>
497
+ <a name='L432'></a><a href='#L432'>432</a>
498
+ <a name='L433'></a><a href='#L433'>433</a>
499
+ <a name='L434'></a><a href='#L434'>434</a>
500
+ <a name='L435'></a><a href='#L435'>435</a>
501
+ <a name='L436'></a><a href='#L436'>436</a>
502
+ <a name='L437'></a><a href='#L437'>437</a>
503
+ <a name='L438'></a><a href='#L438'>438</a>
504
+ <a name='L439'></a><a href='#L439'>439</a>
505
+ <a name='L440'></a><a href='#L440'>440</a>
506
+ <a name='L441'></a><a href='#L441'>441</a>
507
+ <a name='L442'></a><a href='#L442'>442</a>
508
+ <a name='L443'></a><a href='#L443'>443</a>
509
+ <a name='L444'></a><a href='#L444'>444</a>
510
+ <a name='L445'></a><a href='#L445'>445</a>
511
+ <a name='L446'></a><a href='#L446'>446</a>
512
+ <a name='L447'></a><a href='#L447'>447</a>
513
+ <a name='L448'></a><a href='#L448'>448</a>
514
+ <a name='L449'></a><a href='#L449'>449</a>
515
+ <a name='L450'></a><a href='#L450'>450</a>
516
+ <a name='L451'></a><a href='#L451'>451</a>
517
+ <a name='L452'></a><a href='#L452'>452</a>
518
+ <a name='L453'></a><a href='#L453'>453</a>
519
+ <a name='L454'></a><a href='#L454'>454</a>
520
+ <a name='L455'></a><a href='#L455'>455</a>
521
+ <a name='L456'></a><a href='#L456'>456</a>
522
+ <a name='L457'></a><a href='#L457'>457</a>
523
+ <a name='L458'></a><a href='#L458'>458</a>
524
+ <a name='L459'></a><a href='#L459'>459</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</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">1x</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">35x</span>
533
+ <span class="cline-any cline-yes">35x</span>
534
+ <span class="cline-any cline-yes">2x</span>
535
+ <span class="cline-any cline-yes">2x</span>
536
+ <span class="cline-any cline-yes">35x</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">35x</span>
540
+ <span class="cline-any cline-yes">1x</span>
541
+ <span class="cline-any cline-yes">1x</span>
542
+ <span class="cline-any cline-yes">35x</span>
543
+ <span class="cline-any cline-yes">4x</span>
544
+ <span class="cline-any cline-yes">4x</span>
545
+ <span class="cline-any cline-yes">35x</span>
546
+ <span class="cline-any cline-yes">1x</span>
547
+ <span class="cline-any cline-yes">1x</span>
548
+ <span class="cline-any cline-yes">35x</span>
549
+ <span class="cline-any cline-yes">5x</span>
550
+ <span class="cline-any cline-yes">5x</span>
551
+ <span class="cline-any cline-yes">35x</span>
552
+ <span class="cline-any cline-yes">14x</span>
553
+ <span class="cline-any cline-yes">5x</span>
554
+ <span class="cline-any cline-yes">5x</span>
555
+ <span class="cline-any cline-yes">9x</span>
556
+ <span class="cline-any cline-yes">9x</span>
557
+ <span class="cline-any cline-yes">5x</span>
558
+ <span class="cline-any cline-yes">5x</span>
559
+ <span class="cline-any cline-yes">9x</span>
560
+ <span class="cline-any cline-yes">4x</span>
561
+ <span class="cline-any cline-yes">35x</span>
562
+ <span class="cline-any cline-yes">3x</span>
563
+ <span class="cline-any cline-yes">1x</span>
564
+ <span class="cline-any cline-yes">1x</span>
565
+ <span class="cline-any cline-yes">3x</span>
566
+ <span class="cline-any cline-yes">1x</span>
567
+ <span class="cline-any cline-yes">1x</span>
568
+ <span class="cline-any cline-yes">3x</span>
569
+ <span class="cline-any cline-yes">35x</span>
570
+ <span class="cline-any cline-yes">1x</span>
571
+ <span class="cline-any cline-yes">35x</span>
572
+ <span class="cline-any cline-yes">35x</span>
573
+ <span class="cline-any cline-no">&nbsp;</span>
574
+ <span class="cline-any cline-no">&nbsp;</span>
575
+ <span class="cline-any cline-yes">35x</span>
576
+ <span class="cline-any cline-yes">35x</span>
577
+ <span class="cline-any cline-yes">35x</span>
578
+ <span class="cline-any cline-yes">35x</span>
579
+ <span class="cline-any cline-yes">1x</span>
580
+ <span class="cline-any cline-yes">11x</span>
581
+ <span class="cline-any cline-yes">11x</span>
582
+ <span class="cline-any cline-yes">19x</span>
583
+ <span class="cline-any cline-yes">19x</span>
584
+ <span class="cline-any cline-yes">19x</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-yes">19x</span>
588
+ <span class="cline-any cline-yes">1x</span>
589
+ <span class="cline-any cline-yes">1x</span>
590
+ <span class="cline-any cline-yes">19x</span>
591
+ <span class="cline-any cline-no">&nbsp;</span>
592
+ <span class="cline-any cline-no">&nbsp;</span>
593
+ <span class="cline-any cline-yes">19x</span>
594
+ <span class="cline-any cline-yes">4x</span>
595
+ <span class="cline-any cline-yes">4x</span>
596
+ <span class="cline-any cline-yes">19x</span>
597
+ <span class="cline-any cline-yes">11x</span>
598
+ <span class="cline-any cline-yes">1x</span>
599
+ <span class="cline-any cline-yes">7x</span>
600
+ <span class="cline-any cline-yes">7x</span>
601
+ <span class="cline-any cline-yes">10x</span>
602
+ <span class="cline-any cline-yes">10x</span>
603
+ <span class="cline-any cline-yes">1x</span>
604
+ <span class="cline-any cline-yes">1x</span>
605
+ <span class="cline-any cline-yes">10x</span>
606
+ <span class="cline-any cline-no">&nbsp;</span>
607
+ <span class="cline-any cline-no">&nbsp;</span>
608
+ <span class="cline-any cline-yes">10x</span>
609
+ <span class="cline-any cline-no">&nbsp;</span>
610
+ <span class="cline-any cline-no">&nbsp;</span>
611
+ <span class="cline-any cline-yes">10x</span>
612
+ <span class="cline-any cline-no">&nbsp;</span>
613
+ <span class="cline-any cline-no">&nbsp;</span>
614
+ <span class="cline-any cline-yes">10x</span>
615
+ <span class="cline-any cline-no">&nbsp;</span>
616
+ <span class="cline-any cline-no">&nbsp;</span>
617
+ <span class="cline-any cline-yes">10x</span>
618
+ <span class="cline-any cline-yes">7x</span>
619
+ <span class="cline-any cline-yes">4x</span>
620
+ <span class="cline-any cline-yes">4x</span>
621
+ <span class="cline-any cline-yes">7x</span>
622
+ <span class="cline-any cline-no">&nbsp;</span>
623
+ <span class="cline-any cline-no">&nbsp;</span>
624
+ <span class="cline-any cline-yes">7x</span>
625
+ <span class="cline-any cline-yes">1x</span>
626
+ <span class="cline-any cline-yes">24x</span>
627
+ <span class="cline-any cline-yes">24x</span>
628
+ <span class="cline-any cline-no">&nbsp;</span>
629
+ <span class="cline-any cline-no">&nbsp;</span>
630
+ <span class="cline-any cline-yes">24x</span>
631
+ <span class="cline-any cline-yes">5x</span>
632
+ <span class="cline-any cline-yes">5x</span>
633
+ <span class="cline-any cline-yes">19x</span>
634
+ <span class="cline-any cline-yes">19x</span>
635
+ <span class="cline-any cline-yes">24x</span>
636
+ <span class="cline-any cline-yes">11x</span>
637
+ <span class="cline-any cline-yes">24x</span>
638
+ <span class="cline-any cline-yes">7x</span>
639
+ <span class="cline-any cline-yes">24x</span>
640
+ <span class="cline-any cline-yes">1x</span>
641
+ <span class="cline-any cline-yes">24x</span>
642
+ <span class="cline-any cline-yes">24x</span>
643
+ <span class="cline-any cline-yes">1x</span>
644
+ <span class="cline-any cline-yes">30x</span>
645
+ <span class="cline-any cline-yes">30x</span>
646
+ <span class="cline-any cline-yes">1x</span>
647
+ <span class="cline-any cline-yes">1x</span>
648
+ <span class="cline-any cline-yes">30x</span>
649
+ <span class="cline-any cline-yes">10x</span>
650
+ <span class="cline-any cline-yes">2x</span>
651
+ <span class="cline-any cline-yes">2x</span>
652
+ <span class="cline-any cline-yes">8x</span>
653
+ <span class="cline-any cline-yes">8x</span>
654
+ <span class="cline-any cline-yes">8x</span>
655
+ <span class="cline-any cline-yes">8x</span>
656
+ <span class="cline-any cline-yes">30x</span>
657
+ <span class="cline-any cline-yes">2x</span>
658
+ <span class="cline-any cline-yes">2x</span>
659
+ <span class="cline-any cline-yes">30x</span>
660
+ <span class="cline-any cline-yes">2x</span>
661
+ <span class="cline-any cline-yes">2x</span>
662
+ <span class="cline-any cline-yes">30x</span>
663
+ <span class="cline-any cline-yes">7x</span>
664
+ <span class="cline-any cline-yes">7x</span>
665
+ <span class="cline-any cline-yes">2x</span>
666
+ <span class="cline-any cline-yes">2x</span>
667
+ <span class="cline-any cline-yes">7x</span>
668
+ <span class="cline-any cline-yes">1x</span>
669
+ <span class="cline-any cline-yes">1x</span>
670
+ <span class="cline-any cline-yes">4x</span>
671
+ <span class="cline-any cline-yes">4x</span>
672
+ <span class="cline-any cline-yes">4x</span>
673
+ <span class="cline-any cline-yes">30x</span>
674
+ <span class="cline-any cline-yes">9x</span>
675
+ <span class="cline-any cline-yes">9x</span>
676
+ <span class="cline-any cline-yes">16x</span>
677
+ <span class="cline-any cline-no">&nbsp;</span>
678
+ <span class="cline-any cline-no">&nbsp;</span>
679
+ <span class="cline-any cline-yes">16x</span>
680
+ <span class="cline-any cline-yes">1x</span>
681
+ <span class="cline-any cline-yes">1x</span>
682
+ <span class="cline-any cline-yes">15x</span>
683
+ <span class="cline-any cline-yes">15x</span>
684
+ <span class="cline-any cline-yes">8x</span>
685
+ <span class="cline-any cline-yes">30x</span>
686
+ <span class="cline-any cline-yes">1x</span>
687
+ <span class="cline-any cline-yes">15x</span>
688
+ <span class="cline-any cline-yes">15x</span>
689
+ <span class="cline-any cline-yes">43x</span>
690
+ <span class="cline-any cline-yes">1x</span>
691
+ <span class="cline-any cline-yes">1x</span>
692
+ <span class="cline-any cline-yes">43x</span>
693
+ <span class="cline-any cline-yes">10x</span>
694
+ <span class="cline-any cline-yes">8x</span>
695
+ <span class="cline-any cline-yes">7x</span>
696
+ <span class="cline-any cline-yes">7x</span>
697
+ <span class="cline-any cline-yes">7x</span>
698
+ <span class="cline-any cline-yes">1x</span>
699
+ <span class="cline-any cline-yes">1x</span>
700
+ <span class="cline-any cline-yes">8x</span>
701
+ <span class="cline-any cline-yes">8x</span>
702
+ <span class="cline-any cline-yes">43x</span>
703
+ <span class="cline-any cline-yes">9x</span>
704
+ <span class="cline-any cline-yes">9x</span>
705
+ <span class="cline-any cline-yes">9x</span>
706
+ <span class="cline-any cline-yes">9x</span>
707
+ <span class="cline-any cline-yes">15x</span>
708
+ <span class="cline-any cline-no">&nbsp;</span>
709
+ <span class="cline-any cline-no">&nbsp;</span>
710
+ <span class="cline-any cline-yes">15x</span>
711
+ <span class="cline-any cline-yes">1x</span>
712
+ <span class="cline-any cline-yes">1x</span>
713
+ <span class="cline-any cline-yes">145x</span>
714
+ <span class="cline-any cline-yes">145x</span>
715
+ <span class="cline-any cline-no">&nbsp;</span>
716
+ <span class="cline-any cline-no">&nbsp;</span>
717
+ <span class="cline-any cline-yes">145x</span>
718
+ <span class="cline-any cline-yes">1x</span>
719
+ <span class="cline-any cline-yes">1x</span>
720
+ <span class="cline-any cline-yes">145x</span>
721
+ <span class="cline-any cline-yes">15x</span>
722
+ <span class="cline-any cline-yes">15x</span>
723
+ <span class="cline-any cline-yes">15x</span>
724
+ <span class="cline-any cline-yes">129x</span>
725
+ <span class="cline-any cline-yes">145x</span>
726
+ <span class="cline-any cline-yes">1x</span>
727
+ <span class="cline-any cline-yes">1x</span>
728
+ <span class="cline-any cline-yes">145x</span>
729
+ <span class="cline-any cline-yes">1x</span>
730
+ <span class="cline-any cline-yes">1x</span>
731
+ <span class="cline-any cline-yes">145x</span>
732
+ <span class="cline-any cline-no">&nbsp;</span>
733
+ <span class="cline-any cline-no">&nbsp;</span>
734
+ <span class="cline-any cline-yes">145x</span>
735
+ <span class="cline-any cline-yes">11x</span>
736
+ <span class="cline-any cline-yes">2x</span>
737
+ <span class="cline-any cline-yes">2x</span>
738
+ <span class="cline-any cline-yes">11x</span>
739
+ <span class="cline-any cline-yes">6x</span>
740
+ <span class="cline-any cline-yes">6x</span>
741
+ <span class="cline-any cline-yes">11x</span>
742
+ <span class="cline-any cline-yes">145x</span>
743
+ <span class="cline-any cline-yes">95x</span>
744
+ <span class="cline-any cline-yes">1x</span>
745
+ <span class="cline-any cline-yes">1x</span>
746
+ <span class="cline-any cline-yes">102x</span>
747
+ <span class="cline-any cline-yes">145x</span>
748
+ <span class="cline-any cline-yes">1x</span>
749
+ <span class="cline-any cline-yes">1x</span>
750
+ <span class="cline-any cline-yes">145x</span>
751
+ <span class="cline-any cline-yes">75x</span>
752
+ <span class="cline-any cline-yes">90x</span>
753
+ <span class="cline-any cline-yes">145x</span>
754
+ <span class="cline-any cline-yes">4x</span>
755
+ <span class="cline-any cline-yes">4x</span>
756
+ <span class="cline-any cline-yes">3x</span>
757
+ <span class="cline-any cline-yes">4x</span>
758
+ <span class="cline-any cline-yes">4x</span>
759
+ <span class="cline-any cline-yes">4x</span>
760
+ <span class="cline-any cline-yes">86x</span>
761
+ <span class="cline-any cline-yes">145x</span>
762
+ <span class="cline-any cline-yes">8x</span>
763
+ <span class="cline-any cline-yes">8x</span>
764
+ <span class="cline-any cline-yes">145x</span>
765
+ <span class="cline-any cline-no">&nbsp;</span>
766
+ <span class="cline-any cline-no">&nbsp;</span>
767
+ <span class="cline-any cline-no">&nbsp;</span>
768
+ <span class="cline-any cline-no">&nbsp;</span>
769
+ <span class="cline-any cline-yes">145x</span>
770
+ <span class="cline-any cline-no">&nbsp;</span>
771
+ <span class="cline-any cline-no">&nbsp;</span>
772
+ <span class="cline-any cline-yes">145x</span>
773
+ <span class="cline-any cline-yes">1x</span>
774
+ <span class="cline-any cline-yes">111x</span>
775
+ <span class="cline-any cline-yes">111x</span>
776
+ <span class="cline-any cline-yes">111x</span>
777
+ <span class="cline-any cline-yes">110x</span>
778
+ <span class="cline-any cline-yes">111x</span>
779
+ <span class="cline-any cline-yes">5x</span>
780
+ <span class="cline-any cline-yes">5x</span>
781
+ <span class="cline-any cline-yes">105x</span>
782
+ <span class="cline-any cline-yes">105x</span>
783
+ <span class="cline-any cline-yes">111x</span>
784
+ <span class="cline-any cline-yes">145x</span>
785
+ <span class="cline-any cline-yes">145x</span>
786
+ <span class="cline-any cline-yes">145x</span>
787
+ <span class="cline-any cline-no">&nbsp;</span>
788
+ <span class="cline-any cline-no">&nbsp;</span>
789
+ <span class="cline-any cline-yes">86x</span>
790
+ <span class="cline-any cline-yes">86x</span>
791
+ <span class="cline-any cline-yes">46x</span>
792
+ <span class="cline-any cline-yes">111x</span>
793
+ <span class="cline-any cline-yes">19x</span>
794
+ <span class="cline-any cline-yes">27x</span>
795
+ <span class="cline-any cline-yes">7x</span>
796
+ <span class="cline-any cline-yes">1x</span>
797
+ <span class="cline-any cline-yes">1x</span>
798
+ <span class="cline-any cline-yes">7x</span>
799
+ <span class="cline-any cline-yes">2x</span>
800
+ <span class="cline-any cline-yes">2x</span>
801
+ <span class="cline-any cline-yes">4x</span>
802
+ <span class="cline-any cline-yes">7x</span>
803
+ <span class="cline-any cline-yes">2x</span>
804
+ <span class="cline-any cline-yes">2x</span>
805
+ <span class="cline-any cline-yes">7x</span>
806
+ <span class="cline-any cline-yes">20x</span>
807
+ <span class="cline-any cline-yes">4x</span>
808
+ <span class="cline-any cline-yes">4x</span>
809
+ <span class="cline-any cline-yes">19x</span>
810
+ <span class="cline-any cline-yes">19x</span>
811
+ <span class="cline-any cline-yes">111x</span>
812
+ <span class="cline-any cline-yes">1x</span>
813
+ <span class="cline-any cline-yes">15x</span>
814
+ <span class="cline-any cline-yes">15x</span>
815
+ <span class="cline-any cline-yes">15x</span>
816
+ <span class="cline-any cline-yes">15x</span>
817
+ <span class="cline-any cline-yes">15x</span>
818
+ <span class="cline-any cline-yes">1x</span>
819
+ <span class="cline-any cline-yes">1x</span>
820
+ <span class="cline-any cline-yes">14x</span>
821
+ <span class="cline-any cline-yes">14x</span>
822
+ <span class="cline-any cline-yes">14x</span>
823
+ <span class="cline-any cline-yes">15x</span>
824
+ <span class="cline-any cline-yes">1x</span>
825
+ <span class="cline-any cline-yes">1x</span>
826
+ <span class="cline-any cline-yes">39x</span>
827
+ <span class="cline-any cline-yes">39x</span>
828
+ <span class="cline-any cline-no">&nbsp;</span>
829
+ <span class="cline-any cline-no">&nbsp;</span>
830
+ <span class="cline-any cline-yes">39x</span>
831
+ <span class="cline-any cline-yes">1x</span>
832
+ <span class="cline-any cline-yes">1x</span>
833
+ <span class="cline-any cline-yes">38x</span>
834
+ <span class="cline-any cline-yes">39x</span>
835
+ <span class="cline-any cline-yes">1x</span>
836
+ <span class="cline-any cline-yes">1x</span>
837
+ <span class="cline-any cline-yes">39x</span>
838
+ <span class="cline-any cline-yes">1x</span>
839
+ <span class="cline-any cline-yes">1x</span>
840
+ <span class="cline-any cline-yes">39x</span>
841
+ <span class="cline-any cline-yes">1x</span>
842
+ <span class="cline-any cline-yes">1x</span>
843
+ <span class="cline-any cline-yes">39x</span>
844
+ <span class="cline-any cline-no">&nbsp;</span>
845
+ <span class="cline-any cline-no">&nbsp;</span>
846
+ <span class="cline-any cline-yes">39x</span>
847
+ <span class="cline-any cline-yes">10x</span>
848
+ <span class="cline-any cline-no">&nbsp;</span>
849
+ <span class="cline-any cline-no">&nbsp;</span>
850
+ <span class="cline-any cline-yes">10x</span>
851
+ <span class="cline-any cline-yes">6x</span>
852
+ <span class="cline-any cline-yes">6x</span>
853
+ <span class="cline-any cline-yes">10x</span>
854
+ <span class="cline-any cline-yes">39x</span>
855
+ <span class="cline-any cline-yes">2x</span>
856
+ <span class="cline-any cline-yes">2x</span>
857
+ <span class="cline-any cline-yes">39x</span>
858
+ <span class="cline-any cline-yes">21x</span>
859
+ <span class="cline-any cline-yes">21x</span>
860
+ <span class="cline-any cline-yes">6x</span>
861
+ <span class="cline-any cline-yes">6x</span>
862
+ <span class="cline-any cline-yes">15x</span>
863
+ <span class="cline-any cline-yes">15x</span>
864
+ <span class="cline-any cline-yes">21x</span>
865
+ <span class="cline-any cline-yes">6x</span>
866
+ <span class="cline-any cline-yes">6x</span>
867
+ <span class="cline-any cline-yes">6x</span>
868
+ <span class="cline-any cline-yes">6x</span>
869
+ <span class="cline-any cline-no">&nbsp;</span>
870
+ <span class="cline-any cline-no">&nbsp;</span>
871
+ <span class="cline-any cline-yes">39x</span>
872
+ <span class="cline-any cline-yes">1x</span>
873
+ <span class="cline-any cline-yes">39x</span>
874
+ <span class="cline-any cline-yes">39x</span>
875
+ <span class="cline-any cline-yes">39x</span>
876
+ <span class="cline-any cline-yes">39x</span>
877
+ <span class="cline-any cline-yes">39x</span>
878
+ <span class="cline-any cline-yes">39x</span>
879
+ <span class="cline-any cline-yes">39x</span>
880
+ <span class="cline-any cline-yes">1x</span>
881
+ <span class="cline-any cline-yes">45x</span>
882
+ <span class="cline-any cline-yes">45x</span>
883
+ <span class="cline-any cline-yes">45x</span>
884
+ <span class="cline-any cline-yes">44x</span>
885
+ <span class="cline-any cline-yes">45x</span>
886
+ <span class="cline-any cline-yes">5x</span>
887
+ <span class="cline-any cline-yes">5x</span>
888
+ <span class="cline-any cline-yes">39x</span>
889
+ <span class="cline-any cline-yes">39x</span>
890
+ <span class="cline-any cline-yes">45x</span>
891
+ <span class="cline-any cline-yes">40x</span>
892
+ <span class="cline-any cline-yes">39x</span>
893
+ <span class="cline-any cline-yes">40x</span>
894
+ <span class="cline-any cline-yes">11x</span>
895
+ <span class="cline-any cline-yes">11x</span>
896
+ <span class="cline-any cline-yes">12x</span>
897
+ <span class="cline-any cline-yes">40x</span>
898
+ <span class="cline-any cline-yes">1x</span>
899
+ <span class="cline-any cline-yes">1x</span>
900
+ <span class="cline-any cline-yes">11x</span>
901
+ <span class="cline-any cline-yes">11x</span>
902
+ <span class="cline-any cline-yes">45x</span>
903
+ <span class="cline-any cline-yes">1x</span>
904
+ <span class="cline-any cline-yes">7x</span>
905
+ <span class="cline-any cline-yes">7x</span>
906
+ <span class="cline-any cline-yes">7x</span>
907
+ <span class="cline-any cline-yes">1x</span>
908
+ <span class="cline-any cline-yes">7x</span>
909
+ <span class="cline-any cline-yes">7x</span>
910
+ <span class="cline-any cline-yes">7x</span>
911
+ <span class="cline-any cline-yes">1x</span>
912
+ <span class="cline-any cline-yes">7x</span>
913
+ <span class="cline-any cline-yes">7x</span>
914
+ <span class="cline-any cline-yes">7x</span>
915
+ <span class="cline-any cline-yes">1x</span>
916
+ <span class="cline-any cline-no">&nbsp;</span>
917
+ <span class="cline-any cline-no">&nbsp;</span>
918
+ <span class="cline-any cline-no">&nbsp;</span>
919
+ <span class="cline-any cline-yes">1x</span>
920
+ <span class="cline-any cline-no">&nbsp;</span>
921
+ <span class="cline-any cline-no">&nbsp;</span>
922
+ <span class="cline-any cline-no">&nbsp;</span>
923
+ <span class="cline-any cline-no">&nbsp;</span>
924
+ <span class="cline-any cline-no">&nbsp;</span>
925
+ <span class="cline-any cline-no">&nbsp;</span>
926
+ <span class="cline-any cline-no">&nbsp;</span>
927
+ <span class="cline-any cline-no">&nbsp;</span>
928
+ <span class="cline-any cline-no">&nbsp;</span>
929
+ <span class="cline-any cline-no">&nbsp;</span>
930
+ <span class="cline-any cline-yes">1x</span>
931
+ <span class="cline-any cline-yes">1x</span>
932
+ <span class="cline-any cline-no">&nbsp;</span>
933
+ <span class="cline-any cline-no">&nbsp;</span>
934
+ <span class="cline-any cline-no">&nbsp;</span>
935
+ <span class="cline-any cline-no">&nbsp;</span>
936
+ <span class="cline-any cline-no">&nbsp;</span>
937
+ <span class="cline-any cline-no">&nbsp;</span>
938
+ <span class="cline-any cline-no">&nbsp;</span>
939
+ <span class="cline-any cline-no">&nbsp;</span>
940
+ <span class="cline-any cline-no">&nbsp;</span>
941
+ <span class="cline-any cline-yes">1x</span>
942
+ <span class="cline-any cline-yes">235x</span>
943
+ <span class="cline-any cline-yes">235x</span>
944
+ <span class="cline-any cline-yes">7x</span>
945
+ <span class="cline-any cline-yes">7x</span>
946
+ <span class="cline-any cline-yes">235x</span>
947
+ <span class="cline-any cline-yes">2x</span>
948
+ <span class="cline-any cline-yes">2x</span>
949
+ <span class="cline-any cline-yes">2x</span>
950
+ <span class="cline-any cline-yes">235x</span>
951
+ <span class="cline-any cline-yes">2x</span>
952
+ <span class="cline-any cline-yes">2x</span>
953
+ <span class="cline-any cline-yes">235x</span>
954
+ <span class="cline-any cline-yes">2x</span>
955
+ <span class="cline-any cline-yes">2x</span>
956
+ <span class="cline-any cline-yes">222x</span>
957
+ <span class="cline-any cline-yes">235x</span>
958
+ <span class="cline-any cline-yes">2x</span>
959
+ <span class="cline-any cline-yes">2x</span>
960
+ <span class="cline-any cline-yes">235x</span>
961
+ <span class="cline-any cline-yes">235x</span>
962
+ <span class="cline-any cline-yes">5x</span>
963
+ <span class="cline-any cline-yes">5x</span>
964
+ <span class="cline-any cline-yes">235x</span>
965
+ <span class="cline-any cline-yes">1x</span>
966
+ <span class="cline-any cline-yes">1x</span>
967
+ <span class="cline-any cline-yes">235x</span>
968
+ <span class="cline-any cline-yes">235x</span>
969
+ <span class="cline-any cline-yes">235x</span>
970
+ <span class="cline-any cline-yes">235x</span>
971
+ <span class="cline-any cline-yes">235x</span>
972
+ <span class="cline-any cline-yes">235x</span>
973
+ <span class="cline-any cline-yes">235x</span>
974
+ <span class="cline-any cline-yes">235x</span>
975
+ <span class="cline-any cline-yes">64x</span>
976
+ <span class="cline-any cline-yes">235x</span>
977
+ <span class="cline-any cline-no">&nbsp;</span>
978
+ <span class="cline-any cline-no">&nbsp;</span>
979
+ <span class="cline-any cline-yes">235x</span>
980
+ <span class="cline-any cline-yes">1x</span>
981
+ <span class="cline-any cline-yes">1x</span>
982
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">"use strict";
983
+ &nbsp;
984
+ const fs = require("fs"),
985
+ path = require("path"),
986
+ nodeResolve = require("resolve");
987
+ &nbsp;
988
+ const columns = require("../common/utils/columns");
989
+ &nbsp;
990
+ function validateBuildRule(build_rule_name, build_rule) {
991
+ if (build_rule == null) {
992
+ throw new Error(`template.yml: build rule “${build_rule_name}” is null`);
993
+ }
994
+ if (typeof build_rule !== "object" || Array.isArray(build_rule)) {
995
+ throw new Error(`template.yml: build rule “${build_rule_name}” must be a mapping`);
996
+ }
997
+ if (!("script" in build_rule)) {
998
+ throw new Error(`template.yml: build rule “${build_rule_name}” has no “script”`);
999
+ }
1000
+ if (typeof build_rule.script !== "string") {
1001
+ throw new Error(`template.yml: build.${build_rule_name}.script must be a string`);
1002
+ }
1003
+ if (!("directory" in build_rule) &amp;&amp; !("files" in build_rule) &amp;&amp; !("watch" in build_rule)) {
1004
+ throw new Error(`template.yml: build rule “${build_rule_name}” has no “directory”, “files” or “watch”`);
1005
+ }
1006
+ if ("directory" in build_rule &amp;&amp; typeof build_rule.directory !== "string") {
1007
+ throw new Error(`template.yml: “build.${build_rule_name}.directory” must be a string`);
1008
+ }
1009
+ if ("files" in build_rule) {
1010
+ if (!Array.isArray(build_rule.files)) {
1011
+ throw new Error(`template.yml: “build.${build_rule_name}.files” must be an array`);
1012
+ }
1013
+ for (const filename of build_rule.files) {
1014
+ if (typeof filename !== "string") {
1015
+ throw new Error(`template.yml: the entries of “build.${build_rule_name}.files” must be strings`);
1016
+ }
1017
+ }
1018
+ }
1019
+ if ("watch" in build_rule) {
1020
+ if ("directory" in build_rule) {
1021
+ throw new Error(`template.yml: build rule “${build_rule_name}” has both “watch” and “directory”`);
1022
+ }
1023
+ if ("files" in build_rule) {
1024
+ throw new Error(`template.yml: build rule “${build_rule_name}” has both “watch” and files`);
1025
+ }
1026
+ }
1027
+ }
1028
+ &nbsp;
1029
+ function validateBuildRules(build_rules) {
1030
+ if (typeof build_rules !== "object" || Array.isArray(build_rules)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1031
+ <span class="cstat-no" title="statement not covered" > throw new Error("template.yml “build” must be a mapping");</span>
1032
+ <span class="cstat-no" title="statement not covered" > }</span>
1033
+ for (let build_rule_name in build_rules) {
1034
+ validateBuildRule(build_rule_name, build_rules[build_rule_name]);
1035
+ }
1036
+ }
1037
+ &nbsp;
1038
+ function validateStringChoices(property, choices) {
1039
+ for (let i = 0; i &lt; choices.length; i++) {
1040
+ const choice = choices[i];
1041
+ if (typeof choice === "string") { continue; }
1042
+ if (!Array.isArray(choice)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1043
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}” has a “choices” field with an element that is neither a string nor an array`);</span>
1044
+ <span class="cstat-no" title="statement not covered" > }</span>
1045
+ if (choice.length != 2 &amp;&amp; choice.length != 3) {
1046
+ throw new Error(`template.yml setting “${property}”: element ${i} of “choices” field has ${choice.length} elements (should be 2)`);
1047
+ }
1048
+ if (typeof choice[0] !== "string") <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1049
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}”: first entry of element ${i} of “choices” field is not a string`);</span>
1050
+ <span class="cstat-no" title="statement not covered" > }</span>
1051
+ if (typeof choice[1] !== "string") {
1052
+ throw new Error(`template.yml setting “${property}”: second entry of element ${i} of “choices” field is not a string`);
1053
+ }
1054
+ }
1055
+ }
1056
+ &nbsp;
1057
+ function validateBooleanChoices(property, choices) {
1058
+ for (let i = 0; i &lt; choices.length; i++) {
1059
+ const choice = choices[i];
1060
+ if (typeof choice === "string") {
1061
+ throw new Error(`template.yml setting “${property}” has a “choices” field with a string element, but is of type boolean`);
1062
+ }
1063
+ if (!Array.isArray(choice)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1064
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}” has a “choices” field with an element that is neither a string nor an array`);</span>
1065
+ <span class="cstat-no" title="statement not covered" > }</span>
1066
+ if (choice.length != 2 <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; choice.length != 3)</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1067
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}”: element ${i} of “choices” field has ${choice.length} elements (should be 2)`);</span>
1068
+ <span class="cstat-no" title="statement not covered" > }</span>
1069
+ if (typeof choice[0] !== "string") <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1070
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}”: first entry of element ${i} of “choices” field is not a string`);</span>
1071
+ <span class="cstat-no" title="statement not covered" > }</span>
1072
+ if (typeof choice[1] !== "boolean") <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1073
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}”: second entry of element ${i} of boolean “choices” field is not a boolean`);</span>
1074
+ <span class="cstat-no" title="statement not covered" > }</span>
1075
+ }
1076
+ if (choices.length !== 2) {
1077
+ throw new Error(`template.yml setting “${property}”: “choices” field for boolean property can only contain one “false” and one “true” option`);
1078
+ }
1079
+ if (choices[0][1] === choices[1][1]) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1080
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}”: “choices” field for boolean property can only contain one “false” and one “true” option`);</span>
1081
+ <span class="cstat-no" title="statement not covered" > }</span>
1082
+ }
1083
+ &nbsp;
1084
+ function validateChoices(property, choices, choices_other, type) {
1085
+ if (!Array.isArray(choices)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1086
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}” has a “choices” field that is not an array`);</span>
1087
+ <span class="cstat-no" title="statement not covered" > }</span>
1088
+ if (typeof choices_other !== "undefined" &amp;&amp; typeof choices_other !== "boolean") {
1089
+ throw new Error(`template.yml setting “${property}” has invalid value for “choices_other”: should be boolean`);
1090
+ }
1091
+ &nbsp;
1092
+ switch (type) {
1093
+ case "string":
1094
+ return validateStringChoices(property, choices);
1095
+ case "boolean":
1096
+ return validateBooleanChoices(property, choices);
1097
+ default:
1098
+ throw new Error(`template.yml setting “${property}” has a “choices” field, but is of type ${type}`);
1099
+ }
1100
+ }
1101
+ &nbsp;
1102
+ function validateConditional(conditional_settings, property, value, conditional) {
1103
+ if (value == null) {
1104
+ throw new Error(`template.yml Conditional setting “${property}” is badly formed or wrongly indented`);
1105
+ }
1106
+ if (typeof value == "string") {
1107
+ if (value == property) {
1108
+ throw new Error(`template.yml setting “${property}” cannot be conditional on itself`);
1109
+ }
1110
+ // Allow shorthand syntax for booleans
1111
+ conditional_settings.add(value);
1112
+ return;
1113
+ }
1114
+ if (typeof value !== "object") {
1115
+ throw new Error(`template.yml setting “${property}” has a “${conditional}” value that is not a string or object`);
1116
+ }
1117
+ if (Object.keys(value).length == 0) {
1118
+ throw new Error(`template.yml setting “${property}” “${conditional}” property must specify a setting to test against`);
1119
+ }
1120
+ if (!Array.isArray(value)) {
1121
+ for (let name in value) {
1122
+ if (name == property) {
1123
+ throw new Error(`template.yml setting “${property}” cannot be conditional on itself`);
1124
+ }
1125
+ if (value[name].length == 0) {
1126
+ throw new Error(`template.yml setting “${property}” “${conditional}” property: value for ${name} is empty`);
1127
+ }
1128
+ conditional_settings.add(name);
1129
+ }
1130
+ }
1131
+ for (let i = 0; i &lt; value.length; i++) {
1132
+ const condition = value[i];
1133
+ for (let name in condition) {
1134
+ if (name == property) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1135
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}” cannot be conditional on itself`);</span>
1136
+ <span class="cstat-no" title="statement not covered" > }</span>
1137
+ if (condition[name].length == 0) {
1138
+ throw new Error(`template.yml setting “${property}” “${conditional}” property: condition for ${name} is empty`);
1139
+ }
1140
+ conditional_settings.add(name);
1141
+ }
1142
+ }
1143
+ }
1144
+ &nbsp;
1145
+ function validateImport(template_directory, setting) {
1146
+ for (const k in setting) {
1147
+ if (k != "property" &amp;&amp; k != "import" &amp;&amp; k != "overrides" &amp;&amp; k != "show_if" &amp;&amp; k != "hide_if") {
1148
+ throw new Error(`template.yml: Unexpected property '${k}' in import`);
1149
+ }
1150
+ if (k == "overrides") {
1151
+ if (!Array.isArray(setting.overrides)) { throw new Error(`template.yml Setting import overrides must be an array`); }
1152
+ setting.overrides.forEach(function(override) {
1153
+ if (!("property" in override) &amp;&amp; !("tag" in override)) { throw new Error(`template.yml Setting import overrides must each specify overridden “property” or “tag”`); }
1154
+ if (("property" in override) &amp;&amp; ("tag" in override)) { throw new Error(`template.yml Setting import overrides cannot contain both “property” and “tag” property`); }
1155
+ if (![undefined, "replace", "extend"].includes(override.method)) {
1156
+ throw new Error(`template.yml Setting import override “method” method must be either “replace” or “extend”`);
1157
+ }
1158
+ });
1159
+ }
1160
+ }
1161
+ &nbsp;
1162
+ const module_name = setting.import;
1163
+ &nbsp;
1164
+ const target_path = nodeResolve.sync(path.join(module_name, "settings.yml"), { basedir: template_directory });
1165
+ if (!fs.existsSync(target_path)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1166
+ <span class="cstat-no" title="statement not covered" > throw new Error("template.yml: Imported settings not found at " + target_path);</span>
1167
+ <span class="cstat-no" title="statement not covered" > }</span>
1168
+ }
1169
+ &nbsp;
1170
+ const VALID_SETTING_TYPES = new Set(["number", "string", "text", "html", "code", "boolean", "color", "colors", "url", "font", "hidden"]);
1171
+ function validateSetting(template_directory, conditional_settings, setting) {
1172
+ if (typeof setting !== "object" || Array.isArray(setting)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1173
+ <span class="cstat-no" title="statement not covered" > throw new Error("template.yml: setting must be a mapping");</span>
1174
+ <span class="cstat-no" title="statement not covered" > }</span>
1175
+ if (!("property" in setting)) {
1176
+ throw new Error("template.yml setting must specify a property:");
1177
+ }
1178
+ if ("import" in setting) {
1179
+ validateImport(template_directory, setting);
1180
+ return;
1181
+ }
1182
+ const property = setting.property;
1183
+ if (!("name" in setting) &amp;&amp; !("choices" in setting)) {
1184
+ throw new Error(`template.yml setting “${property}” must specify a name:`);
1185
+ }
1186
+ if (!("type" in setting)) {
1187
+ throw new Error(`template.yml setting “${property}” must specify a type:`);
1188
+ }
1189
+ if (!VALID_SETTING_TYPES.has(setting.type)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1190
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}” has invalid type “${setting.type}”`);</span>
1191
+ <span class="cstat-no" title="statement not covered" > }</span>
1192
+ if ("optional" in setting) {
1193
+ if (setting.type !== "number" &amp;&amp; setting.type !== "font" &amp;&amp; setting.type !== "color") {
1194
+ throw new Error(`The “optional” property is only supported for “number”, “color” and “font” type settings`);
1195
+ }
1196
+ if (typeof setting.optional !== "boolean") {
1197
+ throw new Error(`template.yml setting “${property}” has an invalid value for “optional”: should be true or false`);
1198
+ }
1199
+ }
1200
+ if ("choices" in setting) { validateChoices(property, setting.choices, setting.choices_other, setting.type); }
1201
+ else if ("choices_other" in setting) {
1202
+ throw new Error(`template.yml setting “${property}” has a “choices_other” field, but no choices:`);
1203
+ }
1204
+ &nbsp;
1205
+ if ("show_if" in setting &amp;&amp; "hide_if" in setting) {
1206
+ throw new Error(`template.yml setting “${property}” has both “show_if” and “hide_if” properties: there can only be one`);
1207
+ }
1208
+ if ("show_if" in setting) { validateConditional(conditional_settings, property, setting.show_if, "show_if"); }
1209
+ else if ("hide_if" in setting) { validateConditional(conditional_settings, property, setting.hide_if, "hide_if"); }
1210
+ &nbsp;
1211
+ if ("new_section" in setting &amp;&amp; typeof setting.new_section !== "boolean" &amp;&amp; typeof setting.new_section !== "string") {
1212
+ let type = typeof setting.new_section;
1213
+ if (setting.new_section == null) { type = "null"; }
1214
+ else if (Array.isArray(setting.new_section)) { type = "array"; }
1215
+ &nbsp;
1216
+ throw new Error(`template.yml setting “${property}” new_section property must be a boolean or string, not ${type}`);
1217
+ }
1218
+ &nbsp;
1219
+ if ("width" in setting &amp;&amp; (typeof setting.width !== "string" || !/^(full|half|quarter|three quarters)$/.test(setting.width))) {
1220
+ throw new Error(`template.yml setting “${property}” has unsupported width property: must be “full”, “half”, “quarter” or “three quarters”`);
1221
+ }
1222
+ if ("size" in setting) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1223
+ <span class="cstat-no" title="statement not covered" > const can_set_size = setting.type == "code" || setting.type == "text" || setting.type == "html" || (setting.type == "string" &amp;&amp; setting.style == "buttons");</span>
1224
+ <span class="cstat-no" title="statement not covered" > if (!can_set_size) { throw new Error(`template.yml setting “${property}” has a “size” property; this requires type “text”, “code” or “html”, or type “string” with ”style: buttons”`); }</span>
1225
+ <span class="cstat-no" title="statement not covered" > else if (setting.size !== "large" &amp;&amp; setting.size !== "small") { throw new Error(`template.yml setting “${property}” has unsupported size property: must be “large” or “small”`); }</span>
1226
+ <span class="cstat-no" title="statement not covered" > }</span>
1227
+ if ("editor" in setting <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; setting.type != "html")</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1228
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml setting “${property}” has an “editor” field, but is not of type “html”`);</span>
1229
+ <span class="cstat-no" title="statement not covered" > }</span>
1230
+ }
1231
+ &nbsp;
1232
+ function validateSettings(template_directory, settings, bindings) {
1233
+ // Null settings are allowed, and are equivalent to an empty array
1234
+ if (settings == null) { return; }
1235
+ &nbsp;
1236
+ if (!Array.isArray(settings)) {
1237
+ throw new Error("template.yml: “settings” must be an array");
1238
+ }
1239
+ const conditional_settings = new Set();
1240
+ const setting_properties = new Set();
1241
+ for (let setting of settings) {
1242
+ if (typeof setting === "string") <span class="branch-0 cbranch-no" title="branch not covered" >{ continue; }</span>
1243
+ validateSetting(template_directory, conditional_settings, setting);
1244
+ if (setting_properties.has(setting.property)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1245
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml: there is more than one setting for property “${setting.property}”`);</span>
1246
+ <span class="cstat-no" title="statement not covered" > }</span>
1247
+ setting_properties.add(setting.property);
1248
+ }
1249
+ &nbsp;
1250
+ if (conditional_settings.size &gt; 0) {
1251
+ conditional_settings.forEach(function(conditional_setting) {
1252
+ if (/^data\./.test(conditional_setting)) {
1253
+ if (!/^data\.\w+\.\w+(\.type)?$/.test(conditional_setting)) {
1254
+ throw new Error(`template.yml: “show_if” or “hide_if” property specifies invalid data binding or column type “${conditional_setting}”`);
1255
+ }
1256
+ if (!bindings || !Array.isArray(bindings)) {
1257
+ throw new Error(`template.yml: “show_if” or “hide_if” property refers to data binding “${conditional_setting}” when none are defined`);
1258
+ }
1259
+ const conditional = conditional_setting.split(".");
1260
+ if (bindings.findIndex((binding) =&gt; (binding.dataset == conditional[1] &amp;&amp; binding.key == conditional[2])) == -1) {
1261
+ throw new Error(`template.yml: “show_if” or “hide_if” property refers to non-existent data binding “${conditional_setting}”`);
1262
+ }
1263
+ }
1264
+ else if (!setting_properties.has(conditional_setting) &amp;&amp; !setting_properties.has(conditional_setting.split(".")[0])) {
1265
+ throw new Error(`template.yml: “show_if” or “hide_if” property refers to non-existent setting “${conditional_setting}”`);
1266
+ }
1267
+ });
1268
+ }
1269
+ }
1270
+ &nbsp;
1271
+ function validateColSpec(spec, parser, data_table_names, is_optional) {
1272
+ const double_colon_ix = spec.indexOf("::");
1273
+ if (double_colon_ix == -1) <span class="branch-0 cbranch-no" title="branch not covered" >{ throw new Error("Invalid data binding: " + spec); }</span>
1274
+ const data_table_name = spec.substr(0, double_colon_ix);
1275
+ if (!data_table_names.has(data_table_name)) {
1276
+ throw new Error(`template.yml: data binding refers to “${spec}”, but data file does not exist`);
1277
+ }
1278
+ &nbsp;
1279
+ const col_spec = spec.substr(double_colon_ix + 2);
1280
+ parser(col_spec, is_optional);
1281
+ }
1282
+ &nbsp;
1283
+ const VALID_DATA_BINDING_TYPES = new Set(["column", "columns"]);
1284
+ function validateDataBinding(binding, data_table_names) {
1285
+ if (typeof binding !== "object" || Array.isArray(binding)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1286
+ <span class="cstat-no" title="statement not covered" > throw new Error("template.yml: data binding must be a mapping");</span>
1287
+ <span class="cstat-no" title="statement not covered" > }</span>
1288
+ if (!("name" in binding)) {
1289
+ throw new Error(`template.yml data binding must specify a name`);
1290
+ }
1291
+ const binding_name = binding.name;
1292
+ if (!("dataset" in binding)) {
1293
+ throw new Error(`template.yml data binding “${binding_name}” must specify a dataset`);
1294
+ }
1295
+ if (!("key" in binding)) {
1296
+ throw new Error(`template.yml data binding “${binding_name}” must specify a key`);
1297
+ }
1298
+ if (!("type" in binding)) {
1299
+ throw new Error(`template.yml data binding “${binding_name}” must specify a type`);
1300
+ }
1301
+ if (!VALID_DATA_BINDING_TYPES.has(binding.type)) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1302
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml data binding “${binding_name}” has invalid type “${binding.type}”`);</span>
1303
+ <span class="cstat-no" title="statement not covered" > }</span>
1304
+ if ("optional" in binding) {
1305
+ if (binding.type !== "column") <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1306
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml “optional” property is only allows for “column” bindings`);</span>
1307
+ <span class="cstat-no" title="statement not covered" > }</span>
1308
+ if (typeof binding.optional !== "boolean") {
1309
+ throw new Error(`template.yml “optional” property of data binding “${binding_name}” must be a boolean`);
1310
+ }
1311
+ }
1312
+ if (!(binding.type in binding) &amp;&amp; !binding.optional) {
1313
+ throw new Error(`template.yml non-optional data binding “${binding_name}” must specify ${binding.type}`);
1314
+ }
1315
+ if (binding.type == "column") {
1316
+ if ("column" in binding) {
1317
+ if (typeof binding.column !== "string") {
1318
+ throw new Error(`template.yml: “column” property of data binding “${binding_name}” must be a string`);
1319
+ }
1320
+ validateColSpec(binding.column, columns.parseColumn, data_table_names, binding.optional);
1321
+ }
1322
+ }
1323
+ else if (binding.type == "columns") {
1324
+ if (typeof binding.columns !== "string") {
1325
+ throw new Error(`template.yml: “columns” property of data binding “${binding_name}” must be a string`);
1326
+ }
1327
+ <span class="cstat-no" title="statement not covered" ><span class="branch-0 cbranch-no" title="branch not covered" > validateColSpec(binding.columns, columns.parseColumns, data_table_names);</span></span>
1328
+ <span class="cstat-no" title="statement not covered" > }</span>
1329
+ }
1330
+ &nbsp;
1331
+ function getDataTableNames(data_directory) {
1332
+ return new Set(
1333
+ fs.readdirSync(data_directory)
1334
+ .filter(filename =&gt; filename.endsWith(".csv"))
1335
+ .map(filename =&gt; filename.substr(0, filename.length - 4)),
1336
+ );
1337
+ }
1338
+ &nbsp;
1339
+ function validateDataBindings(bindings, data_directory) {
1340
+ // Null bindings are allowed, and are equivalent to an empty array
1341
+ if (bindings == null) { return; }
1342
+ &nbsp;
1343
+ if (!Array.isArray(bindings)) {
1344
+ throw new Error("template.yml: “data” must be an array");
1345
+ }
1346
+ const data_table_names = getDataTableNames(data_directory);
1347
+ const datasets = new Map();
1348
+ for (let binding of bindings) {
1349
+ if (typeof binding === "string") { continue; }
1350
+ validateDataBinding(binding, data_table_names);
1351
+ if (!datasets.has(binding.dataset)) {
1352
+ datasets.set(binding.dataset, new Set());
1353
+ }
1354
+ const dataset = datasets.get(binding.dataset);
1355
+ if (dataset.has(binding.key)) {
1356
+ throw new Error(`template.yml: there is more than one data binding with dataset “${binding.dataset}” and key “${binding.key}”`);
1357
+ }
1358
+ dataset.add(binding.key);
1359
+ }
1360
+ }
1361
+ &nbsp;
1362
+ function validateCredits(credits) {
1363
+ if (typeof credits !== "string") { throw new Error(`template.yml: Credits must be a string`); }
1364
+ }
1365
+ &nbsp;
1366
+ function validateImageDownload(image_download) {
1367
+ if (typeof image_download !== "boolean") { throw new Error(`template.yml: Bad image_download setting; must be either true or false`); }
1368
+ }
1369
+ &nbsp;
1370
+ function validateSvgDownload(svg_download) {
1371
+ if (typeof svg_download !== "boolean") { throw new Error(`template.yml: Bad svg_download setting; must be either true or false`); }
1372
+ }
1373
+ &nbsp;
1374
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function validateIsPremium(is_premium) {</span></span>
1375
+ <span class="cstat-no" title="statement not covered" > if (typeof is_premium !== "boolean") { throw new Error(`template.yml: Bad is_premium setting; must be either true or false`); }</span>
1376
+ <span class="cstat-no" title="statement not covered" >}</span>
1377
+ &nbsp;
1378
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function validateCategories(categories) {</span></span>
1379
+ <span class="cstat-no" title="statement not covered" > if (!Array.isArray(categories)) {</span>
1380
+ <span class="cstat-no" title="statement not covered" > throw new Error("template.yml: “categories” must be an array");</span>
1381
+ <span class="cstat-no" title="statement not covered" > }</span>
1382
+ <span class="cstat-no" title="statement not covered" > categories.forEach(function(category) {</span>
1383
+ <span class="cstat-no" title="statement not covered" > if (typeof category !== "string") {</span>
1384
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml: category ${category} is not a string`);</span>
1385
+ <span class="cstat-no" title="statement not covered" > }</span>
1386
+ <span class="cstat-no" title="statement not covered" > });</span>
1387
+ <span class="cstat-no" title="statement not covered" >}</span>
1388
+ &nbsp;
1389
+ const ALLOWED_TOUR_ATTRIBUTES = new Set(["anchor", "text", "position", "direction", "trigger", "delay", "button_text"]);
1390
+ <span class="cstat-no" title="statement not covered" ><span class="fstat-no" title="function not covered" >function validateTour(tour) {</span></span>
1391
+ <span class="cstat-no" title="statement not covered" > tour.forEach(function(step) {</span>
1392
+ <span class="cstat-no" title="statement not covered" > for (let name in step) {</span>
1393
+ <span class="cstat-no" title="statement not covered" > if (!ALLOWED_TOUR_ATTRIBUTES.has(name)) {</span>
1394
+ <span class="cstat-no" title="statement not covered" > throw new Error(`template.yml: tour has unexpected attribute ${name}`);</span>
1395
+ <span class="cstat-no" title="statement not covered" > }</span>
1396
+ <span class="cstat-no" title="statement not covered" > }</span>
1397
+ <span class="cstat-no" title="statement not covered" > });</span>
1398
+ <span class="cstat-no" title="statement not covered" >}</span>
1399
+ &nbsp;
1400
+ function validateConfig(config, template_directory) {
1401
+ if (config == null || typeof config !== "object" || Array.isArray(config)) {
1402
+ throw new Error("template.yml must define a mapping");
1403
+ }
1404
+ if (!("id" in config)) {
1405
+ // The empty string is permitted here. The publish command checks this explicitly.
1406
+ throw new Error("template.yml must specify an id:");
1407
+ }
1408
+ if (!("name" in config)) {
1409
+ throw new Error("template.yml must specify a name:");
1410
+ }
1411
+ if (!("author" in config)) {
1412
+ throw new Error("template.yml must specify an author:");
1413
+ }
1414
+ // We treat description: as non-mandatory for now
1415
+ if (!("sdk_version" in config)) {
1416
+ throw new Error("template.yml must specify an sdk_version:");
1417
+ }
1418
+ if ("credits" in config) { validateCredits(config.credits); }
1419
+ if ("is_master_slide" in config &amp;&amp; typeof config.is_master_slide !== "boolean") {
1420
+ throw new Error("template.yml: Bad is_master_slide setting; must be either true or false");
1421
+ }
1422
+ if ("autoheight" in config) {
1423
+ throw new Error("template.yml: autoheight is no longer supported. You can use `Flourish.setHeight()` to dynamically adjust the height, if needed.");
1424
+ }
1425
+ if ("image_download" in config) { validateImageDownload(config.image_download); }
1426
+ if ("svg_download" in config) { validateSvgDownload(config.svg_download); }
1427
+ if ("is_premium" in config) <span class="branch-0 cbranch-no" title="branch not covered" >{ validateIsPremium(config.is_premium); }</span>
1428
+ if ("build" in config) { validateBuildRules(config.build); }
1429
+ if ("data" in config) { validateDataBindings(config.data, path.join(template_directory, "data")); }
1430
+ if ("settings" in config) { validateSettings(template_directory, config.settings, config.data); }
1431
+ if ("categories" in config) <span class="branch-0 cbranch-no" title="branch not covered" >{ validateCategories(config.categories); }</span>
1432
+ if ("tour" in config) <span class="branch-0 cbranch-no" title="branch not covered" >{ validateTour(config.tour); }</span>
1433
+ &nbsp;
1434
+ if ("joinable_data" in config <span class="branch-0 cbranch-no" title="branch not covered" >&amp;&amp; typeof config.joinable_data !== "boolean")</span> <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
1435
+ <span class="cstat-no" title="statement not covered" > throw new Error("template.yml: Bad joinable_data setting; must be either true or false");</span>
1436
+ <span class="cstat-no" title="statement not covered" > }</span>
1437
+ }
1438
+ &nbsp;
1439
+ module.exports = validateConfig;
1440
+ &nbsp;</pre></td></tr></table></pre>
1441
+
1442
+ <div class='push'></div><!-- for sticky footer -->
1443
+ </div><!-- /wrapper -->
1444
+ <div class='footer quiet pad2 space-top1 center small'>
1445
+ Code coverage generated by
1446
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
1447
+ at 2025-09-14T22:52:55.226Z
1448
+ </div>
1449
+ <script src="../prettify.js"></script>
1450
+ <script>
1451
+ window.onload = function () {
1452
+ prettyPrint();
1453
+ };
1454
+ </script>
1455
+ <script src="../sorter.js"></script>
1456
+ <script src="../block-navigation.js"></script>
1457
+ </body>
1458
+ </html>
1459
+