tnp-helpers 13.0.37 → 13.1.1

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 (223) hide show
  1. package/app.d.ts +1 -1
  2. package/app.js +6 -6
  3. package/app.js.map +1 -1
  4. package/browser/README.md +24 -24
  5. package/browser/esm2020/lib/base-component.mjs +48 -48
  6. package/browser/esm2020/lib/base-formly-component.mjs +126 -126
  7. package/browser/esm2020/lib/condition-wait.mjs +53 -53
  8. package/browser/esm2020/lib/constants.mjs +7 -2
  9. package/browser/esm2020/lib/dual-component-ctrl.mjs +120 -120
  10. package/browser/esm2020/lib/helpers-array-obj.mjs +80 -80
  11. package/browser/esm2020/lib/helpers-environment.mjs +30 -30
  12. package/browser/esm2020/lib/helpers-numbers.mjs +5 -5
  13. package/browser/esm2020/lib/helpers-strings-regexes.mjs +48 -48
  14. package/browser/esm2020/lib/helpers-strings.mjs +258 -256
  15. package/browser/esm2020/lib/helpers.mjs +276 -276
  16. package/browser/esm2020/lib/index.mjs +14 -14
  17. package/browser/esm2020/lib/long-press.directive.mjs +112 -112
  18. package/browser/esm2020/lib/project.mjs +414 -405
  19. package/browser/esm2020/lib/resize-service.mjs +20 -20
  20. package/browser/esm2020/public-api.mjs +1 -1
  21. package/browser/esm2020/tnp-helpers.mjs +4 -4
  22. package/browser/fesm2015/tnp-helpers.mjs +1537 -1522
  23. package/browser/fesm2015/tnp-helpers.mjs.map +1 -1
  24. package/browser/fesm2020/tnp-helpers.mjs +1529 -1514
  25. package/browser/fesm2020/tnp-helpers.mjs.map +1 -1
  26. package/browser/lib/base-component.d.ts +17 -17
  27. package/browser/lib/base-formly-component.d.ts +31 -31
  28. package/browser/lib/condition-wait.d.ts +8 -8
  29. package/browser/lib/constants.d.ts +6 -1
  30. package/browser/lib/dual-component-ctrl.d.ts +25 -25
  31. package/browser/lib/helpers-array-obj.d.ts +15 -15
  32. package/browser/lib/helpers-environment.d.ts +5 -5
  33. package/browser/lib/helpers-numbers.d.ts +3 -3
  34. package/browser/lib/helpers-strings-regexes.d.ts +28 -28
  35. package/browser/lib/helpers-strings.d.ts +50 -50
  36. package/browser/lib/helpers.d.ts +28 -28
  37. package/browser/lib/index.d.ts +10 -10
  38. package/browser/lib/long-press.directive.d.ts +25 -25
  39. package/browser/lib/project.d.ts +91 -91
  40. package/browser/lib/resize-service.d.ts +9 -9
  41. package/browser/public-api.d.ts +1 -1
  42. package/browser/tnp-helpers.d.ts +5 -5
  43. package/client/README.md +24 -24
  44. package/client/esm2020/lib/base-component.mjs +48 -48
  45. package/client/esm2020/lib/base-formly-component.mjs +126 -126
  46. package/client/esm2020/lib/condition-wait.mjs +53 -53
  47. package/client/esm2020/lib/constants.mjs +7 -2
  48. package/client/esm2020/lib/dual-component-ctrl.mjs +120 -120
  49. package/client/esm2020/lib/helpers-array-obj.mjs +80 -80
  50. package/client/esm2020/lib/helpers-environment.mjs +30 -30
  51. package/client/esm2020/lib/helpers-numbers.mjs +5 -5
  52. package/client/esm2020/lib/helpers-strings-regexes.mjs +48 -48
  53. package/client/esm2020/lib/helpers-strings.mjs +258 -256
  54. package/client/esm2020/lib/helpers.mjs +276 -276
  55. package/client/esm2020/lib/index.mjs +14 -14
  56. package/client/esm2020/lib/long-press.directive.mjs +112 -112
  57. package/client/esm2020/lib/project.mjs +414 -405
  58. package/client/esm2020/lib/resize-service.mjs +20 -20
  59. package/client/esm2020/public-api.mjs +1 -1
  60. package/client/esm2020/tnp-helpers.mjs +4 -4
  61. package/client/fesm2015/tnp-helpers.mjs +1537 -1522
  62. package/client/fesm2015/tnp-helpers.mjs.map +1 -1
  63. package/client/fesm2020/tnp-helpers.mjs +1529 -1514
  64. package/client/fesm2020/tnp-helpers.mjs.map +1 -1
  65. package/client/lib/base-component.d.ts +17 -17
  66. package/client/lib/base-formly-component.d.ts +31 -31
  67. package/client/lib/condition-wait.d.ts +8 -8
  68. package/client/lib/constants.d.ts +6 -1
  69. package/client/lib/dual-component-ctrl.d.ts +25 -25
  70. package/client/lib/helpers-array-obj.d.ts +15 -15
  71. package/client/lib/helpers-environment.d.ts +5 -5
  72. package/client/lib/helpers-numbers.d.ts +3 -3
  73. package/client/lib/helpers-strings-regexes.d.ts +28 -28
  74. package/client/lib/helpers-strings.d.ts +50 -50
  75. package/client/lib/helpers.d.ts +28 -28
  76. package/client/lib/index.d.ts +10 -10
  77. package/client/lib/long-press.directive.d.ts +25 -25
  78. package/client/lib/project.d.ts +91 -91
  79. package/client/lib/resize-service.d.ts +9 -9
  80. package/client/public-api.d.ts +1 -1
  81. package/client/tnp-helpers.d.ts +5 -5
  82. package/index.d.ts +1 -1
  83. package/index.js +5 -5
  84. package/index.js.map +1 -1
  85. package/lib/angular.helper.d.ts +22 -22
  86. package/lib/angular.helper.js +50 -49
  87. package/lib/angular.helper.js.map +1 -1
  88. package/lib/base-component.d.ts +1 -1
  89. package/lib/base-component.js +6 -6
  90. package/lib/base-component.js.map +1 -1
  91. package/lib/base-formly-component.d.ts +1 -1
  92. package/lib/base-formly-component.js +6 -6
  93. package/lib/base-formly-component.js.map +1 -1
  94. package/lib/condition-wait.d.ts +8 -8
  95. package/lib/condition-wait.js +94 -94
  96. package/lib/condition-wait.js.map +1 -1
  97. package/lib/constants.d.ts +6 -1
  98. package/lib/constants.js +10 -5
  99. package/lib/constants.js.map +1 -1
  100. package/lib/dual-component-ctrl.d.ts +1 -1
  101. package/lib/dual-component-ctrl.js +6 -6
  102. package/lib/dual-component-ctrl.js.map +1 -1
  103. package/lib/git-project.d.ts +44 -44
  104. package/lib/git-project.js +195 -191
  105. package/lib/git-project.js.map +1 -1
  106. package/lib/helpers-array-obj.d.ts +15 -15
  107. package/lib/helpers-array-obj.js +88 -88
  108. package/lib/helpers-array-obj.js.map +1 -1
  109. package/lib/helpers-cli-tool.backend.d.ts +45 -45
  110. package/lib/helpers-cli-tool.backend.js +293 -293
  111. package/lib/helpers-cli-tool.backend.js.map +1 -1
  112. package/lib/helpers-dependencies.backend.d.ts +11 -11
  113. package/lib/helpers-dependencies.backend.js +105 -105
  114. package/lib/helpers-dependencies.backend.js.map +1 -1
  115. package/lib/helpers-environment.d.ts +5 -5
  116. package/lib/helpers-environment.js +35 -35
  117. package/lib/helpers-environment.js.map +1 -1
  118. package/lib/helpers-file-folders.backend.d.ts +84 -73
  119. package/lib/helpers-file-folders.backend.js +736 -707
  120. package/lib/helpers-file-folders.backend.js.map +1 -1
  121. package/lib/helpers-git.backend.d.ts +35 -35
  122. package/lib/helpers-git.backend.js +545 -534
  123. package/lib/helpers-git.backend.js.map +1 -1
  124. package/lib/helpers-json5.backend.d.ts +16 -16
  125. package/lib/helpers-json5.backend.js +70 -70
  126. package/lib/helpers-json5.backend.js.map +1 -1
  127. package/lib/helpers-morphi-framework.backend.d.ts +4 -4
  128. package/lib/helpers-morphi-framework.backend.js +49 -49
  129. package/lib/helpers-morphi-framework.backend.js.map +1 -1
  130. package/lib/helpers-network.backend.d.ts +8 -8
  131. package/lib/helpers-network.backend.js +48 -48
  132. package/lib/helpers-network.backend.js.map +1 -1
  133. package/lib/helpers-npm.backend.d.ts +3 -3
  134. package/lib/helpers-npm.backend.js +17 -17
  135. package/lib/helpers-npm.backend.js.map +1 -1
  136. package/lib/helpers-numbers.d.ts +3 -3
  137. package/lib/helpers-numbers.js +11 -11
  138. package/lib/helpers-numbers.js.map +1 -1
  139. package/lib/helpers-path.backend.d.ts +7 -7
  140. package/lib/helpers-path.backend.js +36 -35
  141. package/lib/helpers-path.backend.js.map +1 -1
  142. package/lib/helpers-process.backend.d.ts +57 -51
  143. package/lib/helpers-process.backend.js +529 -523
  144. package/lib/helpers-process.backend.js.map +1 -1
  145. package/lib/helpers-strings-regexes.d.ts +28 -28
  146. package/lib/helpers-strings-regexes.js +60 -60
  147. package/lib/helpers-strings-regexes.js.map +1 -1
  148. package/lib/helpers-strings.d.ts +50 -50
  149. package/lib/helpers-strings.js +265 -263
  150. package/lib/helpers-strings.js.map +1 -1
  151. package/lib/helpers-system-terminal.backend.d.ts +5 -5
  152. package/lib/helpers-system-terminal.backend.js +53 -53
  153. package/lib/helpers-system-terminal.backend.js.map +1 -1
  154. package/lib/helpers.d.ts +67 -67
  155. package/lib/helpers.js +391 -372
  156. package/lib/helpers.js.map +1 -1
  157. package/lib/index.d.ts +6 -6
  158. package/lib/index.js +19 -19
  159. package/lib/index.js.map +1 -1
  160. package/lib/long-press.directive.d.ts +22 -22
  161. package/lib/long-press.directive.js +141 -141
  162. package/lib/long-press.directive.js.map +1 -1
  163. package/lib/merge-helpers.backend.d.ts +23 -23
  164. package/lib/merge-helpers.backend.js +108 -108
  165. package/lib/merge-helpers.backend.js.map +1 -1
  166. package/lib/project.d.ts +94 -94
  167. package/lib/project.js +422 -419
  168. package/lib/project.js.map +1 -1
  169. package/lib/resize-service.d.ts +6 -6
  170. package/lib/resize-service.js +24 -24
  171. package/lib/resize-service.js.map +1 -1
  172. package/lib/ts-code/index.d.ts +1 -1
  173. package/lib/ts-code/index.js +7 -7
  174. package/lib/ts-code/index.js.map +1 -1
  175. package/lib/ts-code/ts-code-extractor.d.ts +14 -14
  176. package/lib/ts-code/ts-code-extractor.js +46 -46
  177. package/lib/ts-code/ts-code-extractor.js.map +1 -1
  178. package/lib/ts-code/ts-code-modifier.backend.d.ts +12 -12
  179. package/lib/ts-code/ts-code-modifier.backend.js +70 -70
  180. package/lib/ts-code/ts-code-modifier.backend.js.map +1 -1
  181. package/package.json +3 -3
  182. package/package.json_devDependencies.json +222 -222
  183. package/package.json_tnp.json5 +41 -33
  184. package/tmp-environment.json +48 -45
  185. package/websql/README.md +24 -24
  186. package/websql/esm2020/lib/base-component.mjs +48 -48
  187. package/websql/esm2020/lib/base-formly-component.mjs +126 -126
  188. package/websql/esm2020/lib/condition-wait.mjs +53 -53
  189. package/websql/esm2020/lib/constants.mjs +7 -2
  190. package/websql/esm2020/lib/dual-component-ctrl.mjs +120 -120
  191. package/websql/esm2020/lib/helpers-array-obj.mjs +80 -80
  192. package/websql/esm2020/lib/helpers-environment.mjs +30 -30
  193. package/websql/esm2020/lib/helpers-numbers.mjs +5 -5
  194. package/websql/esm2020/lib/helpers-strings-regexes.mjs +48 -48
  195. package/websql/esm2020/lib/helpers-strings.mjs +258 -256
  196. package/websql/esm2020/lib/helpers.mjs +276 -276
  197. package/websql/esm2020/lib/index.mjs +14 -14
  198. package/websql/esm2020/lib/long-press.directive.mjs +112 -112
  199. package/websql/esm2020/lib/project.mjs +414 -405
  200. package/websql/esm2020/lib/resize-service.mjs +20 -20
  201. package/websql/esm2020/public-api.mjs +1 -1
  202. package/websql/esm2020/tnp-helpers.mjs +4 -4
  203. package/websql/fesm2015/tnp-helpers.mjs +1537 -1522
  204. package/websql/fesm2015/tnp-helpers.mjs.map +1 -1
  205. package/websql/fesm2020/tnp-helpers.mjs +1529 -1514
  206. package/websql/fesm2020/tnp-helpers.mjs.map +1 -1
  207. package/websql/lib/base-component.d.ts +17 -17
  208. package/websql/lib/base-formly-component.d.ts +31 -31
  209. package/websql/lib/condition-wait.d.ts +8 -8
  210. package/websql/lib/constants.d.ts +6 -1
  211. package/websql/lib/dual-component-ctrl.d.ts +25 -25
  212. package/websql/lib/helpers-array-obj.d.ts +15 -15
  213. package/websql/lib/helpers-environment.d.ts +5 -5
  214. package/websql/lib/helpers-numbers.d.ts +3 -3
  215. package/websql/lib/helpers-strings-regexes.d.ts +28 -28
  216. package/websql/lib/helpers-strings.d.ts +50 -50
  217. package/websql/lib/helpers.d.ts +28 -28
  218. package/websql/lib/index.d.ts +10 -10
  219. package/websql/lib/long-press.directive.d.ts +25 -25
  220. package/websql/lib/project.d.ts +91 -91
  221. package/websql/lib/resize-service.d.ts +9 -9
  222. package/websql/public-api.d.ts +1 -1
  223. package/websql/tnp-helpers.d.ts +5 -5
@@ -1,256 +1,258 @@
1
- import { _ } from 'tnp-core/websql';
2
- export class HelpersStrings {
3
- /**
4
- * Example:
5
- *
6
- * const result = interpolateString("I'm {age} years old!")
7
- * .withParameters({ age: 29 });
8
- *
9
- * const result = interpolateString("The {a} says {n}, {n}, {n}!")
10
- * .withParameters({ a: 'cow', n: 'moo' });
11
- *
12
- *
13
- * @param value string to interpolate
14
- * @param parameters object with parametes
15
- */
16
- interpolateString(value) {
17
- if (typeof value !== 'string') {
18
- console.warn('[ss-logic][helper] Value for interpolation is not string: ', value);
19
- return value;
20
- }
21
- return {
22
- withParameters(parameters) {
23
- if (typeof parameters !== 'object') {
24
- console.warn('[ss-logic][helper] Parameters are not a object: ', parameters);
25
- return value;
26
- }
27
- return value.replace(/{([^{}]*)}/g, function (a, b) {
28
- var r = parameters[b];
29
- return typeof r === 'string' || typeof r === 'number' ? r : a;
30
- });
31
- }
32
- };
33
- }
34
- numValue(pixelsCss) {
35
- // tslint:disable-next-line:radix
36
- return parseInt(pixelsCss.replace('px', ''));
37
- }
38
- /**
39
- * examples:
40
- * 'aa bb bb' => ['aa','bb','cc'],
41
- * 'aa' => ['aa']
42
- * ['aa'] => ['aa']
43
- */
44
- splitIfNeed(stringOrArr) {
45
- let res = [];
46
- if (_.isArray(stringOrArr)) {
47
- res = stringOrArr.map(s => {
48
- return s.trim();
49
- });
50
- }
51
- if (_.isString(stringOrArr)) {
52
- res = stringOrArr.split(/\s*[\s,]\s*/);
53
- }
54
- return res.filter(f => !!f && (f.trim() !== ''));
55
- }
56
- removeDoubleOrMoreEmptyLines(s) {
57
- s = s?.split('\n').map(f => f.trimRight()).join('\n');
58
- return s?.replace(/(\r\n|\r|\n){2,}/g, '$1\n');
59
- }
60
- /**
61
- *
62
- * https://stackoverflow.com/a/57129703/1345101
63
- *
64
- * Returns the plural of an English word.
65
- *
66
- * @export
67
- * @param {string} word
68
- * @param {number} [amount]
69
- * @returns {string}
70
- */
71
- plural(word, amount) {
72
- if (amount !== undefined && amount === 1) {
73
- return word;
74
- }
75
- const plural = {
76
- '(quiz)$': "$1zes",
77
- '^(ox)$': "$1en",
78
- '([m|l])ouse$': "$1ice",
79
- '(matr|vert|ind)ix|ex$': "$1ices",
80
- '(x|ch|ss|sh)$': "$1es",
81
- '([^aeiouy]|qu)y$': "$1ies",
82
- '(hive)$': "$1s",
83
- '(?:([^f])fe|([lr])f)$': "$1$2ves",
84
- '(shea|lea|loa|thie)f$': "$1ves",
85
- 'sis$': "ses",
86
- '([ti])um$': "$1a",
87
- '(tomat|potat|ech|her|vet)o$': "$1oes",
88
- '(bu)s$': "$1ses",
89
- '(alias)$': "$1es",
90
- '(octop)us$': "$1i",
91
- '(ax|test)is$': "$1es",
92
- '(us)$': "$1es",
93
- '([^s]+)$': "$1s"
94
- };
95
- const irregular = {
96
- 'move': 'moves',
97
- 'foot': 'feet',
98
- 'goose': 'geese',
99
- 'sex': 'sexes',
100
- 'child': 'children',
101
- 'man': 'men',
102
- 'tooth': 'teeth',
103
- 'person': 'people'
104
- };
105
- const uncountable = [
106
- 'sheep',
107
- 'fish',
108
- 'deer',
109
- 'moose',
110
- 'series',
111
- 'species',
112
- 'money',
113
- 'rice',
114
- 'information',
115
- 'equipment',
116
- 'bison',
117
- 'cod',
118
- 'offspring',
119
- 'pike',
120
- 'salmon',
121
- 'shrimp',
122
- 'swine',
123
- 'trout',
124
- 'aircraft',
125
- 'hovercraft',
126
- 'spacecraft',
127
- 'sugar',
128
- 'tuna',
129
- 'you',
130
- 'wood'
131
- ];
132
- // save some time in the case that singular and plural are the same
133
- if (uncountable.indexOf(word.toLowerCase()) >= 0) {
134
- return word;
135
- }
136
- // check for irregular forms
137
- for (const w in irregular) {
138
- const pattern = new RegExp(`${w}$`, 'i');
139
- const replace = irregular[w];
140
- if (pattern.test(word)) {
141
- return word.replace(pattern, replace);
142
- }
143
- }
144
- // check for matches using regular expressions
145
- for (const reg in plural) {
146
- const pattern = new RegExp(reg, 'i');
147
- if (pattern.test(word)) {
148
- return word.replace(pattern, plural[reg]);
149
- }
150
- }
151
- return word;
152
- }
153
- /**
154
- * https://stackoverflow.com/a/57129703/1345101
155
- *
156
- * Returns the singular of an English word.
157
- *
158
- * @export
159
- * @param {string} word
160
- * @param {number} [amount]
161
- * @returns {string}
162
- */
163
- singular(word, amount) {
164
- if (amount !== undefined && amount !== 1) {
165
- return word;
166
- }
167
- const singular = {
168
- '(quiz)zes$': "$1",
169
- '(matr)ices$': "$1ix",
170
- '(vert|ind)ices$': "$1ex",
171
- '^(ox)en$': "$1",
172
- '(alias)es$': "$1",
173
- '(octop|vir)i$': "$1us",
174
- '(cris|ax|test)es$': "$1is",
175
- '(shoe)s$': "$1",
176
- '(o)es$': "$1",
177
- '(bus)es$': "$1",
178
- '([m|l])ice$': "$1ouse",
179
- '(x|ch|ss|sh)es$': "$1",
180
- '(m)ovies$': "$1ovie",
181
- '(s)eries$': "$1eries",
182
- '([^aeiouy]|qu)ies$': "$1y",
183
- '([lr])ves$': "$1f",
184
- '(tive)s$': "$1",
185
- '(hive)s$': "$1",
186
- '(li|wi|kni)ves$': "$1fe",
187
- '(shea|loa|lea|thie)ves$': "$1f",
188
- '(^analy)ses$': "$1sis",
189
- '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$': "$1$2sis",
190
- '([ti])a$': "$1um",
191
- '(n)ews$': "$1ews",
192
- '(h|bl)ouses$': "$1ouse",
193
- '(corpse)s$': "$1",
194
- '(us)es$': "$1",
195
- 's$': ""
196
- };
197
- const irregular = {
198
- 'move': 'moves',
199
- 'foot': 'feet',
200
- 'goose': 'geese',
201
- 'sex': 'sexes',
202
- 'child': 'children',
203
- 'man': 'men',
204
- 'tooth': 'teeth',
205
- 'person': 'people'
206
- };
207
- const uncountable = [
208
- 'sheep',
209
- 'fish',
210
- 'deer',
211
- 'moose',
212
- 'series',
213
- 'species',
214
- 'money',
215
- 'rice',
216
- 'information',
217
- 'equipment',
218
- 'bison',
219
- 'cod',
220
- 'offspring',
221
- 'pike',
222
- 'salmon',
223
- 'shrimp',
224
- 'swine',
225
- 'trout',
226
- 'aircraft',
227
- 'hovercraft',
228
- 'spacecraft',
229
- 'sugar',
230
- 'tuna',
231
- 'you',
232
- 'wood'
233
- ];
234
- // save some time in the case that singular and plural are the same
235
- if (uncountable.indexOf(word.toLowerCase()) >= 0) {
236
- return word;
237
- }
238
- // check for irregular forms
239
- for (const w in irregular) {
240
- const pattern = new RegExp(`${irregular[w]}$`, 'i');
241
- const replace = w;
242
- if (pattern.test(word)) {
243
- return word.replace(pattern, replace);
244
- }
245
- }
246
- // check for matches using regular expressions
247
- for (const reg in singular) {
248
- const pattern = new RegExp(reg, 'i');
249
- if (pattern.test(word)) {
250
- return word.replace(pattern, singular[reg]);
251
- }
252
- }
253
- return word;
254
- }
255
- }
256
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy1zdHJpbmdzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdG1wLWxpYnMtZm9yLWJ1bmRsZS13ZWJzcWwvdG5wLWhlbHBlcnMvcHJvamVjdHMvdG5wLWhlbHBlcnMvc3JjL2xpYi9oZWxwZXJzLXN0cmluZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXBDLE1BQU0sT0FBTyxjQUFjO0lBRXpCOzs7Ozs7Ozs7Ozs7T0FZRztJQUNILGlCQUFpQixDQUFVLEtBQWE7UUFDdEMsSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLEVBQUU7WUFDN0IsT0FBTyxDQUFDLElBQUksQ0FBQyw0REFBNEQsRUFBRSxLQUFLLENBQUMsQ0FBQztZQUNsRixPQUFPLEtBQUssQ0FBQztTQUNkO1FBRUQsT0FBTztZQUNMLGNBQWMsQ0FBQyxVQUFhO2dCQUMxQixJQUFJLE9BQU8sVUFBVSxLQUFLLFFBQVEsRUFBRTtvQkFDbEMsT0FBTyxDQUFDLElBQUksQ0FBQyxrREFBa0QsRUFBRSxVQUFVLENBQUMsQ0FBQztvQkFDN0UsT0FBTyxLQUFLLENBQUM7aUJBQ2Q7Z0JBQ0QsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxVQUFVLENBQUMsRUFBRSxDQUFDO29CQUNoRCxJQUFJLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3RCLE9BQU8sT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2hFLENBQVEsQ0FBQyxDQUFDO1lBQ1osQ0FBQztTQUNGLENBQUE7SUFFSCxDQUFDO0lBRUQsUUFBUSxDQUFDLFNBQWlCO1FBQ3hCLGlDQUFpQztRQUNqQyxPQUFPLFFBQVEsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFD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UCxNQUFNO1lBQ04sS0FBSztZQUNMLE1BQU07U0FDUCxDQUFBO1FBQ0QsbUVBQW1FO1FBQ25FLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDaEQsT0FBTyxJQUFJLENBQUE7U0FDWjtRQUNELDRCQUE0QjtRQUM1QixLQUFLLE1BQU0sQ0FBQyxJQUFJLFNBQVMsRUFBRTtZQUN6QixNQUFNLE9BQU8sR0FBRyxJQUFJLE1BQU0sQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFBO1lBQ25ELE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQTtZQUNqQixJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ3RCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUE7YUFDdEM7U0FDRjtRQUNELDhDQUE4QztRQUM5QyxLQUFLLE1BQU0sR0FBRyxJQUFJLFFBQVEsRUFBRTtZQUMxQixNQUFNLE9BQU8sR0FBRyxJQUFJLE1BQU0sQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUE7WUFDcEMsSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUN0QixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO2FBQzVDO1NBQ0Y7UUFDRCxPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7Q0FFRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IF8gfSBmcm9tICd0bnAtY29yZS93ZWJzcWwnO1xuXG5leHBvcnQgY2xhc3MgSGVscGVyc1N0cmluZ3Mge1xuXG4gIC8qKlxuICAgKiBFeGFtcGxlOlxuICAgKlxuICAgKiBjb25zdCByZXN1bHQgPSBpbnRlcnBvbGF0ZVN0cmluZyhcIkknbSB7YWdlfSB5ZWFycyBvbGQhXCIpXG4gICAqIC53aXRoUGFyYW1ldGVycyh7IGFnZTogMjkgfSk7XG4gICAqXG4gICAqIGNvbnN0IHJlc3VsdCA9IGludGVycG9sYXRlU3RyaW5nKFwiVGhlIHthfSBzYXlzIHtufSwge259LCB7bn0hXCIpXG4gICAqIC53aXRoUGFyYW1ldGVycyh7IGE6ICdjb3cnLCBuOiAnbW9vJyB9KTtcbiAgICpcbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIHN0cmluZyB0byBpbnRlcnBvbGF0ZVxuICAgKiBAcGFyYW0gcGFyYW1ldGVycyBvYmplY3Qgd2l0aCBwYXJhbWV0ZXNcbiAgICovXG4gIGludGVycG9sYXRlU3RyaW5nPFQgPSBhbnk+KHZhbHVlOiBzdHJpbmcpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnc3RyaW5nJykge1xuICAgICAgY29uc29sZS53YXJuKCdbc3MtbG9naWNdW2hlbHBlcl0gVmFsdWUgZm9yIGludGVycG9sYXRpb24gaXMgbm90IHN0cmluZzogJywgdmFsdWUpO1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICB3aXRoUGFyYW1ldGVycyhwYXJhbWV0ZXJzOiBUKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcGFyYW1ldGVycyAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBjb25zb2xlLndhcm4oJ1tzcy1sb2dpY11baGVscGVyXSBQYXJhbWV0ZXJzIGFyZSBub3QgYSBvYmplY3Q6ICcsIHBhcmFtZXRlcnMpO1xuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWUucmVwbGFjZSgveyhbXnt9XSopfS9nLCBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgIHZhciByID0gcGFyYW1ldGVyc1tiXTtcbiAgICAgICAgICByZXR1cm4gdHlwZW9mIHIgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiByID09PSAnbnVtYmVyJyA/IHIgOiBhO1xuICAgICAgICB9IGFzIGFueSk7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICBudW1WYWx1ZShwaXhlbHNDc3M6IHN0cmluZykge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpyYWRpeFxuICAgIHJldHVybiBwYXJzZUludChwaXhlbHNDc3MucmVwbGFjZSgncHgnLCAnJykpO1xuICB9XG5cbiAgLyoqXG4gICAqIGV4YW1wbGVzOlxuICAgKiAnYWEgYmIgYmInID0+IFsnYWEnLCdiYicsJ2NjJ10sXG4gICAqICdhYScgPT4gWydhYSddXG4gICAqIFsnYWEnXSA9PiBbJ2FhJ11cbiAgICovXG4gIHNwbGl0SWZOZWVkKHN0cmluZ09yQXJyOiBzdHJpbmcgfCBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgICBsZXQgcmVzID0gW107XG4gICAgaWYgKF8uaXNBcnJheShzdHJpbmdPckFycikpIHtcbiAgICAgIHJlcyA9IHN0cmluZ09yQXJyLm1hcChzID0+IHtcbiAgICAgICAgcmV0dXJuIHMudHJpbSgpO1xuICAgICAgfSlcbiAgICB9XG4gICAgaWYgKF8uaXNTdHJpbmcoc3RyaW5nT3JBcnIpKSB7XG4gICAgICByZXMgPSBzdHJpbmdPckFyci5zcGxpdCgvXFxzKltcXHMsXVxccyovKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcy5maWx0ZXIoZiA9PiAhIWYgJiYgKGYudHJpbSgpICE9PSAnJykpO1xuICB9XG5cbiAgcmVtb3ZlRG91YmxlT3JNb3JlRW1wdHlMaW5lcyhzOiBzdHJpbmcpIHtcbiAgICBzID0gcz8uc3BsaXQoJ1xcbicpLm1hcChmID0+IGYudHJpbVJpZ2h0KCkpLmpvaW4oJ1xcbicpO1xuICAgIHJldHVybiBzPy5yZXBsYWNlKC8oXFxyXFxufFxccnxcXG4pezIsfS9nLCAnJDFcXG4nKTtcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNTcxMjk3MDMvMTM0NTEwMVxuICAgKlxuICAgKiBSZXR1cm5zIHRoZSBwbHVyYWwgb2YgYW4gRW5nbGlzaCB3b3JkLlxuICAgKlxuICAgKiBAZXhwb3J0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSB3b3JkXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbYW1vdW50XVxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgcGx1cmFsKHdvcmQ6IHN0cmluZywgYW1vdW50PzogbnVtYmVyKTogc3RyaW5nIHtcbiAgICBpZiAoYW1vdW50ICE9PSB1bmRlZmluZWQgJiYgYW1vdW50ID09PSAxKSB7XG4gICAgICByZXR1cm4gd29yZFxuICAgIH1cbiAgICBjb25zdCBwbHVyYWw6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICAnKHF1aXopJCc6IFwiJDF6ZXNcIixcbiAgICAgICdeKG94KSQnOiBcIiQxZW5cIixcbiAgICAgICcoW218bF0pb3VzZSQnOiBcIiQxaWNlXCIsXG4gICAgICAnKG1hdHJ8dmVydHxpbmQpaXh8ZXgkJzogXCIkMWljZXNcIixcbiAgICAgICcoeHxjaHxzc3xzaCkkJzogXCIkMWVzXCIsXG4gICAgICAnKFteYWVpb3V5XXxxdSl5JCc6IFwiJDFpZXNcIixcbiAgICAgICcoaGl2ZSkkJzogXCIkMXNcIixcbiAgICAgICcoPzooW15mXSlmZXwoW2xyXSlmKSQnOiBcIiQxJDJ2ZXNcIixcbiAgICAgICcoc2hlYXxsZWF8bG9hfHRoaWUpZiQnOiBcIiQxdmVzXCIsXG4gICAgICAnc2lzJCc6IFwic2VzXCIsXG4gICAgICAnKFt0aV0pdW0kJzogXCIkMWFcIixcbiAgICAgICcodG9tYXR8cG90YXR8ZWNofGhlcnx2ZXQpbyQnOiBcIiQxb2VzXCIsXG4gICAgICAnKGJ1KXMkJzogXCIkMXNlc1wiLFxuICAgICAgJyhhbGlhcykkJzogXCIkMWVzXCIsXG4gICAgICAnKG9jdG9wKXVzJCc6IFwiJDFpXCIsXG4gICAgICAnKGF4fHRlc3QpaXMkJzogXCIkMWVzXCIsXG4gICAgICAnKHVzKSQnOiBcIiQxZXNcIixcbiAgICAgICcoW15zXSspJCc6IFwiJDFzXCJcbiAgICB9XG4gICAgY29uc3QgaXJyZWd1bGFyOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgJ21vdmUnOiAnbW92ZXMnLFxuICAgICAgJ2Zvb3QnOiAnZmVldCcsXG4gICAgICAnZ29vc2UnOiAnZ2Vlc2UnLFxuICAgICAgJ3NleCc6ICdzZXhlcycsXG4gICAgICAnY2hpbGQnOiAnY2hpbGRyZW4nLFxuICAgICAgJ21hbic6ICdtZW4nLFxuICAgICAgJ3Rvb3RoJzogJ3RlZXRoJyxcbiAgICAgICdwZXJzb24nOiAncGVvcGxlJ1xuICAgIH1cbiAgICBjb25zdCB1bmNvdW50YWJsZTogc3RyaW5nW10gPSBbXG4gICAgICAnc2hlZXAnLFxuICAgICAgJ2Zpc2gnLFxuICAgICAgJ2RlZXInLFxuICAgICAgJ21vb3NlJyxcbiAgICAgICdzZXJpZXMnLFxuICAgICAgJ3NwZWNpZXMnLFxuICAgICAgJ21vbmV5JyxcbiAgICAgICdyaWNlJyxcbiAgICAgICdpbmZvcm1hdGlvbicsXG4gICAgICAnZXF1aXBtZW50JyxcbiAgICAgICdiaXNvbicsXG4gICAgICAnY29kJyxcbiAgICAgICdvZmZzcHJpbmcnLFxuICAgICAgJ3Bpa2UnLFxuICAgICAgJ3NhbG1vbicsXG4gICAgICAnc2hyaW1wJyxcbiAgICAgICdzd2luZScsXG4gICAgICAndHJvdXQnLFxuICAgICAgJ2FpcmNyYWZ0JyxcbiAgICAgICdob3ZlcmNyYWZ0JyxcbiAgICAgICdzcGFjZWNyYWZ0JyxcbiAgICAgICdzdWdhcicsXG4gICAgICAndHVuYScsXG4gICAgICAneW91JyxcbiAgICAgICd3b29kJ1xuICAgIF1cbiAgICAvLyBzYXZlIHNvbWUgdGltZSBpbiB0aGUgY2FzZSB0aGF0IHNpbmd1bGFyIGFuZCBwbHVyYWwgYXJlIHRoZSBzYW1lXG4gICAgaWYgKHVuY291bnRhYmxlLmluZGV4T2Yod29yZC50b0xvd2VyQ2FzZSgpKSA+PSAwKSB7XG4gICAgICByZXR1cm4gd29yZFxuICAgIH1cbiAgICAvLyBjaGVjayBmb3IgaXJyZWd1bGFyIGZvcm1zXG4gICAgZm9yIChjb25zdCB3IGluIGlycmVndWxhcikge1xuICAgICAgY29uc3QgcGF0dGVybiA9IG5ldyBSZWdFeHAoYCR7d30kYCwgJ2knKVxuICAgICAgY29uc3QgcmVwbGFjZSA9IGlycmVndWxhclt3XVxuICAgICAgaWYgKHBhdHRlcm4udGVzdCh3b3JkKSkge1xuICAgICAgICByZXR1cm4gd29yZC5yZXBsYWNlKHBhdHRlcm4sIHJlcGxhY2UpXG4gICAgICB9XG4gICAgfVxuICAgIC8vIGNoZWNrIGZvciBtYXRjaGVzIHVzaW5nIHJlZ3VsYXIgZXhwcmVzc2lvbnNcbiAgICBmb3IgKGNvbnN0IHJlZyBpbiBwbHVyYWwpIHtcbiAgICAgIGNvbnN0IHBhdHRlcm4gPSBuZXcgUmVnRXhwKHJlZywgJ2knKVxuICAgICAgaWYgKHBhdHRlcm4udGVzdCh3b3JkKSkge1xuICAgICAgICByZXR1cm4gd29yZC5yZXBsYWNlKHBhdHRlcm4sIHBsdXJhbFtyZWddKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gd29yZFxuICB9XG5cblxuICAvKipcbiAgICogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzU3MTI5NzAzLzEzNDUxMDFcbiAgICpcbiAgKiBSZXR1cm5zIHRoZSBzaW5ndWxhciBvZiBhbiBFbmdsaXNoIHdvcmQuXG4gICpcbiAgKiBAZXhwb3J0XG4gICogQHBhcmFtIHtzdHJpbmd9IHdvcmRcbiAgKiBAcGFyYW0ge251bWJlcn0gW2Ftb3VudF1cbiAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAqL1xuICBzaW5ndWxhcih3b3JkOiBzdHJpbmcsIGFtb3VudD86IG51bWJlcik6IHN0cmluZyB7XG4gICAgaWYgKGFtb3VudCAhPT0gdW5kZWZpbmVkICYmIGFtb3VudCAhPT0gMSkge1xuICAgICAgcmV0dXJuIHdvcmRcbiAgICB9XG4gICAgY29uc3Qgc2luZ3VsYXI6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICAnKHF1aXopemVzJCc6IFwiJDFcIixcbiAgICAgICcobWF0cilpY2VzJCc6IFwiJDFpeFwiLFxuICAgICAgJyh2ZXJ0fGluZClpY2VzJCc6IFwiJDFleFwiLFxuICAgICAgJ14ob3gpZW4kJzogXCIkMVwiLFxuICAgICAgJyhhbGlhcyllcyQnOiBcIiQxXCIsXG4gICAgICAnKG9jdG9wfHZpcilpJCc6IFwiJDF1c1wiLFxuICAgICAgJyhjcmlzfGF4fHRlc3QpZXMkJzogXCIkMWlzXCIsXG4gICAgICAnKHNob2UpcyQnOiBcIiQxXCIsXG4gICAgICAnKG8pZXMkJzogXCIkMVwiLFxuICAgICAgJyhidXMpZXMkJzogXCIkMVwiLFxuICAgICAgJyhbbXxsXSlpY2UkJzogXCIkMW91c2VcIixcbiAgICAgICcoeHxjaHxzc3xzaCllcyQnOiBcIiQxXCIsXG4gICAgICAnKG0pb3ZpZXMkJzogXCIkMW92aWVcIixcbiAgICAgICcocyllcmllcyQnOiBcIiQxZXJpZXNcIixcbiAgICAgICcoW15hZWlvdXldfHF1KWllcyQnOiBcIiQxeVwiLFxuICAgICAgJyhbbHJdKXZlcyQnOiBcIiQxZlwiLFxuICAgICAgJyh0aXZlKXMkJzogXCIkMVwiLFxuICAgICAgJyhoaXZlKXMkJzogXCIkMVwiLFxuICAgICAgJyhsaXx3aXxrbmkpdmVzJCc6IFwiJDFmZVwiLFxuICAgICAgJyhzaGVhfGxvYXxsZWF8dGhpZSl2ZXMkJzogXCIkMWZcIixcbiAgICAgICcoXmFuYWx5KXNlcyQnOiBcIiQxc2lzXCIsXG4gICAgICAnKChhKW5hbHl8KGIpYXwoZClpYWdub3wocClhcmVudGhlfChwKXJvZ25vfChzKXlub3B8KHQpaGUpc2VzJCc6IFwiJDEkMnNpc1wiLFxuICAgICAgJyhbdGldKWEkJzogXCIkMXVtXCIsXG4gICAgICAnKG4pZXdzJCc6IFwiJDFld3NcIixcbiAgICAgICcoaHxibClvdXNlcyQnOiBcIiQxb3VzZVwiLFxuICAgICAgJyhjb3Jwc2UpcyQnOiBcIiQxXCIsXG4gICAgICAnKHVzKWVzJCc6IFwiJDFcIixcbiAgICAgICdzJCc6IFwiXCJcbiAgICB9XG4gICAgY29uc3QgaXJyZWd1bGFyOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgJ21vdmUnOiAnbW92ZXMnLFxuICAgICAgJ2Zvb3QnOiAnZmVldCcsXG4gICAgICAnZ29vc2UnOiAnZ2Vlc2UnLFxuICAgICAgJ3NleCc6ICdzZXhlcycsXG4gICAgICAnY2hpbGQnOiAnY2hpbGRyZW4nLFxuICAgICAgJ21hbic6ICdtZW4nLFxuICAgICAgJ3Rvb3RoJzogJ3RlZXRoJyxcbiAgICAgICdwZXJzb24nOiAncGVvcGxlJ1xuICAgIH1cbiAgICBjb25zdCB1bmNvdW50YWJsZTogc3RyaW5nW10gPSBbXG4gICAgICAnc2hlZXAnLFxuICAgICAgJ2Zpc2gnLFxuICAgICAgJ2RlZXInLFxuICAgICAgJ21vb3NlJyxcbiAgICAgICdzZXJpZXMnLFxuICAgICAgJ3NwZWNpZXMnLFxuICAgICAgJ21vbmV5JyxcbiAgICAgICdyaWNlJyxcbiAgICAgICdpbmZvcm1hdGlvbicsXG4gICAgICAnZXF1aXBtZW50JyxcbiAgICAgICdiaXNvbicsXG4gICAgICAnY29kJyxcbiAgICAgICdvZmZzcHJpbmcnLFxuICAgICAgJ3Bpa2UnLFxuICAgICAgJ3NhbG1vbicsXG4gICAgICAnc2hyaW1wJyxcbiAgICAgICdzd2luZScsXG4gICAgICAndHJvdXQnLFxuICAgICAgJ2FpcmNyYWZ0JyxcbiAgICAgICdob3ZlcmNyYWZ0JyxcbiAgICAgICdzcGFjZWNyYWZ0JyxcbiAgICAgICdzdWdhcicsXG4gICAgICAndHVuYScsXG4gICAgICAneW91JyxcbiAgICAgICd3b29kJ1xuICAgIF1cbiAgICAvLyBzYXZlIHNvbWUgdGltZSBpbiB0aGUgY2FzZSB0aGF0IHNpbmd1bGFyIGFuZCBwbHVyYWwgYXJlIHRoZSBzYW1lXG4gICAgaWYgKHVuY291bnRhYmxlLmluZGV4T2Yod29yZC50b0xvd2VyQ2FzZSgpKSA+PSAwKSB7XG4gICAgICByZXR1cm4gd29yZFxuICAgIH1cbiAgICAvLyBjaGVjayBmb3IgaXJyZWd1bGFyIGZvcm1zXG4gICAgZm9yIChjb25zdCB3IGluIGlycmVndWxhcikge1xuICAgICAgY29uc3QgcGF0dGVybiA9IG5ldyBSZWdFeHAoYCR7aXJyZWd1bGFyW3ddfSRgLCAnaScpXG4gICAgICBjb25zdCByZXBsYWNlID0gd1xuICAgICAgaWYgKHBhdHRlcm4udGVzdCh3b3JkKSkge1xuICAgICAgICByZXR1cm4gd29yZC5yZXBsYWNlKHBhdHRlcm4sIHJlcGxhY2UpXG4gICAgICB9XG4gICAgfVxuICAgIC8vIGNoZWNrIGZvciBtYXRjaGVzIHVzaW5nIHJlZ3VsYXIgZXhwcmVzc2lvbnNcbiAgICBmb3IgKGNvbnN0IHJlZyBpbiBzaW5ndWxhcikge1xuICAgICAgY29uc3QgcGF0dGVybiA9IG5ldyBSZWdFeHAocmVnLCAnaScpXG4gICAgICBpZiAocGF0dGVybi50ZXN0KHdvcmQpKSB7XG4gICAgICAgIHJldHVybiB3b3JkLnJlcGxhY2UocGF0dGVybiwgc2luZ3VsYXJbcmVnXSlcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHdvcmRcbiAgfVxuXG59XG5cbiJdfQ==
1
+ import { _ } from 'tnp-core/websql';
2
+ import { Helpers } from './index';
3
+ export class HelpersStrings {
4
+ /**
5
+ * Example:
6
+ *
7
+ * const result = interpolateString("I'm {age} years old!")
8
+ * .withParameters({ age: 29 });
9
+ *
10
+ * const result = interpolateString("The {a} says {n}, {n}, {n}!")
11
+ * .withParameters({ a: 'cow', n: 'moo' });
12
+ *
13
+ *
14
+ * @param value string to interpolate
15
+ * @param parameters object with parametes
16
+ */
17
+ interpolateString(value) {
18
+ if (typeof value !== 'string') {
19
+ Helpers.warn('[ss-logic][helper] Value for interpolation is not string: ', value);
20
+ return value;
21
+ }
22
+ return {
23
+ withParameters(parameters) {
24
+ if (typeof parameters !== 'object') {
25
+ Helpers.log(parameters);
26
+ Helpers.warn('[ss-logic][helper] Parameters are not a object: ');
27
+ return value;
28
+ }
29
+ return value.replace(/{([^{}]*)}/g, function (a, b) {
30
+ var r = parameters[b];
31
+ return typeof r === 'string' || typeof r === 'number' ? r : a;
32
+ });
33
+ }
34
+ };
35
+ }
36
+ numValue(pixelsCss) {
37
+ // tslint:disable-next-line:radix
38
+ return parseInt(pixelsCss.replace('px', ''));
39
+ }
40
+ /**
41
+ * examples:
42
+ * 'aa bb bb' => ['aa','bb','cc'],
43
+ * 'aa' => ['aa']
44
+ * ['aa'] => ['aa']
45
+ */
46
+ splitIfNeed(stringOrArr) {
47
+ let res = [];
48
+ if (_.isArray(stringOrArr)) {
49
+ res = stringOrArr.map(s => {
50
+ return s.trim();
51
+ });
52
+ }
53
+ if (_.isString(stringOrArr)) {
54
+ res = stringOrArr.split(/\s*[\s,]\s*/);
55
+ }
56
+ return res.filter(f => !!f && (f.trim() !== ''));
57
+ }
58
+ removeDoubleOrMoreEmptyLines(s) {
59
+ s = s?.split('\n').map(f => f.trimRight()).join('\n');
60
+ return s?.replace(/(\r\n|\r|\n){2,}/g, '$1\n');
61
+ }
62
+ /**
63
+ *
64
+ * https://stackoverflow.com/a/57129703/1345101
65
+ *
66
+ * Returns the plural of an English word.
67
+ *
68
+ * @export
69
+ * @param {string} word
70
+ * @param {number} [amount]
71
+ * @returns {string}
72
+ */
73
+ plural(word, amount) {
74
+ if (amount !== undefined && amount === 1) {
75
+ return word;
76
+ }
77
+ const plural = {
78
+ '(quiz)$': "$1zes",
79
+ '^(ox)$': "$1en",
80
+ '([m|l])ouse$': "$1ice",
81
+ '(matr|vert|ind)ix|ex$': "$1ices",
82
+ '(x|ch|ss|sh)$': "$1es",
83
+ '([^aeiouy]|qu)y$': "$1ies",
84
+ '(hive)$': "$1s",
85
+ '(?:([^f])fe|([lr])f)$': "$1$2ves",
86
+ '(shea|lea|loa|thie)f$': "$1ves",
87
+ 'sis$': "ses",
88
+ '([ti])um$': "$1a",
89
+ '(tomat|potat|ech|her|vet)o$': "$1oes",
90
+ '(bu)s$': "$1ses",
91
+ '(alias)$': "$1es",
92
+ '(octop)us$': "$1i",
93
+ '(ax|test)is$': "$1es",
94
+ '(us)$': "$1es",
95
+ '([^s]+)$': "$1s"
96
+ };
97
+ const irregular = {
98
+ 'move': 'moves',
99
+ 'foot': 'feet',
100
+ 'goose': 'geese',
101
+ 'sex': 'sexes',
102
+ 'child': 'children',
103
+ 'man': 'men',
104
+ 'tooth': 'teeth',
105
+ 'person': 'people'
106
+ };
107
+ const uncountable = [
108
+ 'sheep',
109
+ 'fish',
110
+ 'deer',
111
+ 'moose',
112
+ 'series',
113
+ 'species',
114
+ 'money',
115
+ 'rice',
116
+ 'information',
117
+ 'equipment',
118
+ 'bison',
119
+ 'cod',
120
+ 'offspring',
121
+ 'pike',
122
+ 'salmon',
123
+ 'shrimp',
124
+ 'swine',
125
+ 'trout',
126
+ 'aircraft',
127
+ 'hovercraft',
128
+ 'spacecraft',
129
+ 'sugar',
130
+ 'tuna',
131
+ 'you',
132
+ 'wood'
133
+ ];
134
+ // save some time in the case that singular and plural are the same
135
+ if (uncountable.indexOf(word.toLowerCase()) >= 0) {
136
+ return word;
137
+ }
138
+ // check for irregular forms
139
+ for (const w in irregular) {
140
+ const pattern = new RegExp(`${w}$`, 'i');
141
+ const replace = irregular[w];
142
+ if (pattern.test(word)) {
143
+ return word.replace(pattern, replace);
144
+ }
145
+ }
146
+ // check for matches using regular expressions
147
+ for (const reg in plural) {
148
+ const pattern = new RegExp(reg, 'i');
149
+ if (pattern.test(word)) {
150
+ return word.replace(pattern, plural[reg]);
151
+ }
152
+ }
153
+ return word;
154
+ }
155
+ /**
156
+ * https://stackoverflow.com/a/57129703/1345101
157
+ *
158
+ * Returns the singular of an English word.
159
+ *
160
+ * @export
161
+ * @param {string} word
162
+ * @param {number} [amount]
163
+ * @returns {string}
164
+ */
165
+ singular(word, amount) {
166
+ if (amount !== undefined && amount !== 1) {
167
+ return word;
168
+ }
169
+ const singular = {
170
+ '(quiz)zes$': "$1",
171
+ '(matr)ices$': "$1ix",
172
+ '(vert|ind)ices$': "$1ex",
173
+ '^(ox)en$': "$1",
174
+ '(alias)es$': "$1",
175
+ '(octop|vir)i$': "$1us",
176
+ '(cris|ax|test)es$': "$1is",
177
+ '(shoe)s$': "$1",
178
+ '(o)es$': "$1",
179
+ '(bus)es$': "$1",
180
+ '([m|l])ice$': "$1ouse",
181
+ '(x|ch|ss|sh)es$': "$1",
182
+ '(m)ovies$': "$1ovie",
183
+ '(s)eries$': "$1eries",
184
+ '([^aeiouy]|qu)ies$': "$1y",
185
+ '([lr])ves$': "$1f",
186
+ '(tive)s$': "$1",
187
+ '(hive)s$': "$1",
188
+ '(li|wi|kni)ves$': "$1fe",
189
+ '(shea|loa|lea|thie)ves$': "$1f",
190
+ '(^analy)ses$': "$1sis",
191
+ '((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$': "$1$2sis",
192
+ '([ti])a$': "$1um",
193
+ '(n)ews$': "$1ews",
194
+ '(h|bl)ouses$': "$1ouse",
195
+ '(corpse)s$': "$1",
196
+ '(us)es$': "$1",
197
+ 's$': ""
198
+ };
199
+ const irregular = {
200
+ 'move': 'moves',
201
+ 'foot': 'feet',
202
+ 'goose': 'geese',
203
+ 'sex': 'sexes',
204
+ 'child': 'children',
205
+ 'man': 'men',
206
+ 'tooth': 'teeth',
207
+ 'person': 'people'
208
+ };
209
+ const uncountable = [
210
+ 'sheep',
211
+ 'fish',
212
+ 'deer',
213
+ 'moose',
214
+ 'series',
215
+ 'species',
216
+ 'money',
217
+ 'rice',
218
+ 'information',
219
+ 'equipment',
220
+ 'bison',
221
+ 'cod',
222
+ 'offspring',
223
+ 'pike',
224
+ 'salmon',
225
+ 'shrimp',
226
+ 'swine',
227
+ 'trout',
228
+ 'aircraft',
229
+ 'hovercraft',
230
+ 'spacecraft',
231
+ 'sugar',
232
+ 'tuna',
233
+ 'you',
234
+ 'wood'
235
+ ];
236
+ // save some time in the case that singular and plural are the same
237
+ if (uncountable.indexOf(word.toLowerCase()) >= 0) {
238
+ return word;
239
+ }
240
+ // check for irregular forms
241
+ for (const w in irregular) {
242
+ const pattern = new RegExp(`${irregular[w]}$`, 'i');
243
+ const replace = w;
244
+ if (pattern.test(word)) {
245
+ return word.replace(pattern, replace);
246
+ }
247
+ }
248
+ // check for matches using regular expressions
249
+ for (const reg in singular) {
250
+ const pattern = new RegExp(reg, 'i');
251
+ if (pattern.test(word)) {
252
+ return word.replace(pattern, singular[reg]);
253
+ }
254
+ }
255
+ return word;
256
+ }
257
+ }
258
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscGVycy1zdHJpbmdzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vdG1wLWxpYnMtZm9yLWJ1bmRsZS13ZWJzcWwvdG5wLWhlbHBlcnMvcHJvamVjdHMvdG5wLWhlbHBlcnMvc3JjL2xpYi9oZWxwZXJzLXN0cmluZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3BDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFFbEMsTUFBTSxPQUFPLGNBQWM7SUFFekI7Ozs7Ozs7Ozs7OztPQVlHO0lBQ0gsaUJBQWlCLENBQVUsS0FBYTtRQUN0QyxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsRUFBRTtZQUM3QixPQUFPLENBQUMsSUFBSSxDQUFDLDREQUE0RCxFQUFFLEtBQUssQ0FBQyxDQUFDO1lBQ2xGLE9BQU8sS0FBSyxDQUFDO1NBQ2Q7UUFFRCxPQUFPO1lBQ0wsY0FBYyxDQUFDLFVBQWE7Z0JBQzFCLElBQUksT0FBTyxVQUFVLEtBQUssUUFBUSxFQUFFO29CQUNsQyxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQWlCLENBQUMsQ0FBQztvQkFDL0IsT0FBTyxDQUFDLElBQUksQ0FBQyxrREFBa0QsQ0FBQyxDQUFDO29CQUNqRSxPQUFPLEtBQUssQ0FBQztpQkFDZDtnQkFDRCxPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLFVBQVUsQ0FBQyxFQUFFLENBQUM7b0JBQ2hELElBQUksQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDdEIsT0FBTyxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDaEUsQ0FBUSxDQUFDLENBQUM7WUFDWixDQUFDO1NBQ0YsQ0FBQTtJQUVILENBQUM7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O1lBQ1IsUUFBUTtZQUNSLE9BQU87WUFDUCxPQUFPO1lBQ1AsVUFBVTtZQUNWLFlBQVk7WUFDWixZQUFZO1lBQ1osT0FBTztZQUNQLE1BQU07WUFDTixLQUFLO1lBQ0wsTUFBTTtTQUNQLENBQUE7UUFDRCxtRUFBbUU7UUFDbkUsSUFBSSxXQUFXLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNoRCxPQUFPLElBQUksQ0FBQTtTQUNaO1FBQ0QsNEJBQTRCO1FBQzVCLEtBQUssTUFBTSxDQUFDLElBQUksU0FBUyxFQUFFO1lBQ3pCLE1BQU0sT0FBTyxHQUFHLElBQUksTUFBTSxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUE7WUFDbkQsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFBO1lBQ2pCLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRTtnQkFDdEIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQTthQUN0QztTQUNGO1FBQ0QsOENBQThDO1FBQzlDLEtBQUssTUFBTSxHQUFHLElBQUksUUFBUSxFQUFFO1lBQzFCLE1BQU0sT0FBTyxHQUFHLElBQUksTUFBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQTtZQUNwQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ3RCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7YUFDNUM7U0FDRjtRQUNELE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztDQUVGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgXyB9IGZyb20gJ3RucC1jb3JlL3dlYnNxbCc7XG5pbXBvcnQgeyBIZWxwZXJzIH0gZnJvbSAnLi9pbmRleCc7XG5cbmV4cG9ydCBjbGFzcyBIZWxwZXJzU3RyaW5ncyB7XG5cbiAgLyoqXG4gICAqIEV4YW1wbGU6XG4gICAqXG4gICAqIGNvbnN0IHJlc3VsdCA9IGludGVycG9sYXRlU3RyaW5nKFwiSSdtIHthZ2V9IHllYXJzIG9sZCFcIilcbiAgICogLndpdGhQYXJhbWV0ZXJzKHsgYWdlOiAyOSB9KTtcbiAgICpcbiAgICogY29uc3QgcmVzdWx0ID0gaW50ZXJwb2xhdGVTdHJpbmcoXCJUaGUge2F9IHNheXMge259LCB7bn0sIHtufSFcIilcbiAgICogLndpdGhQYXJhbWV0ZXJzKHsgYTogJ2NvdycsIG46ICdtb28nIH0pO1xuICAgKlxuICAgKlxuICAgKiBAcGFyYW0gdmFsdWUgc3RyaW5nIHRvIGludGVycG9sYXRlXG4gICAqIEBwYXJhbSBwYXJhbWV0ZXJzIG9iamVjdCB3aXRoIHBhcmFtZXRlc1xuICAgKi9cbiAgaW50ZXJwb2xhdGVTdHJpbmc8VCA9IGFueT4odmFsdWU6IHN0cmluZykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICBIZWxwZXJzLndhcm4oJ1tzcy1sb2dpY11baGVscGVyXSBWYWx1ZSBmb3IgaW50ZXJwb2xhdGlvbiBpcyBub3Qgc3RyaW5nOiAnLCB2YWx1ZSk7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHdpdGhQYXJhbWV0ZXJzKHBhcmFtZXRlcnM6IFQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBwYXJhbWV0ZXJzICE9PSAnb2JqZWN0Jykge1xuICAgICAgICAgIEhlbHBlcnMubG9nKHBhcmFtZXRlcnMgYXMgYW55KTtcbiAgICAgICAgICBIZWxwZXJzLndhcm4oJ1tzcy1sb2dpY11baGVscGVyXSBQYXJhbWV0ZXJzIGFyZSBub3QgYSBvYmplY3Q6ICcpO1xuICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWUucmVwbGFjZSgveyhbXnt9XSopfS9nLCBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgIHZhciByID0gcGFyYW1ldGVyc1tiXTtcbiAgICAgICAgICByZXR1cm4gdHlwZW9mIHIgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiByID09PSAnbnVtYmVyJyA/IHIgOiBhO1xuICAgICAgICB9IGFzIGFueSk7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICBudW1WYWx1ZShwaXhlbHNDc3M6IHN0cmluZykge1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpyYWRpeFxuICAgIHJldHVybiBwYXJzZUludChwaXhlbHNDc3MucmVwbGFjZSgncHgnLCAnJykpO1xuICB9XG5cbiAgLyoqXG4gICAqIGV4YW1wbGVzOlxuICAgKiAnYWEgYmIgYmInID0+IFsnYWEnLCdiYicsJ2NjJ10sXG4gICAqICdhYScgPT4gWydhYSddXG4gICAqIFsnYWEnXSA9PiBbJ2FhJ11cbiAgICovXG4gIHNwbGl0SWZOZWVkKHN0cmluZ09yQXJyOiBzdHJpbmcgfCBzdHJpbmdbXSk6IHN0cmluZ1tdIHtcbiAgICBsZXQgcmVzID0gW107XG4gICAgaWYgKF8uaXNBcnJheShzdHJpbmdPckFycikpIHtcbiAgICAgIHJlcyA9IHN0cmluZ09yQXJyLm1hcChzID0+IHtcbiAgICAgICAgcmV0dXJuIHMudHJpbSgpO1xuICAgICAgfSlcbiAgICB9XG4gICAgaWYgKF8uaXNTdHJpbmcoc3RyaW5nT3JBcnIpKSB7XG4gICAgICByZXMgPSBzdHJpbmdPckFyci5zcGxpdCgvXFxzKltcXHMsXVxccyovKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlcy5maWx0ZXIoZiA9PiAhIWYgJiYgKGYudHJpbSgpICE9PSAnJykpO1xuICB9XG5cbiAgcmVtb3ZlRG91YmxlT3JNb3JlRW1wdHlMaW5lcyhzOiBzdHJpbmcpIHtcbiAgICBzID0gcz8uc3BsaXQoJ1xcbicpLm1hcChmID0+IGYudHJpbVJpZ2h0KCkpLmpvaW4oJ1xcbicpO1xuICAgIHJldHVybiBzPy5yZXBsYWNlKC8oXFxyXFxufFxccnxcXG4pezIsfS9nLCAnJDFcXG4nKTtcbiAgfVxuXG4gIC8qKlxuICAgKlxuICAgKiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNTcxMjk3MDMvMTM0NTEwMVxuICAgKlxuICAgKiBSZXR1cm5zIHRoZSBwbHVyYWwgb2YgYW4gRW5nbGlzaCB3b3JkLlxuICAgKlxuICAgKiBAZXhwb3J0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSB3b3JkXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbYW1vdW50XVxuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgcGx1cmFsKHdvcmQ6IHN0cmluZywgYW1vdW50PzogbnVtYmVyKTogc3RyaW5nIHtcbiAgICBpZiAoYW1vdW50ICE9PSB1bmRlZmluZWQgJiYgYW1vdW50ID09PSAxKSB7XG4gICAgICByZXR1cm4gd29yZFxuICAgIH1cbiAgICBjb25zdCBwbHVyYWw6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICAnKHF1aXopJCc6IFwiJDF6ZXNcIixcbiAgICAgICdeKG94KSQnOiBcIiQxZW5cIixcbiAgICAgICcoW218bF0pb3VzZSQnOiBcIiQxaWNlXCIsXG4gICAgICAnKG1hdHJ8dmVydHxpbmQpaXh8ZXgkJzogXCIkMWljZXNcIixcbiAgICAgICcoeHxjaHxzc3xzaCkkJzogXCIkMWVzXCIsXG4gICAgICAnKFteYWVpb3V5XXxxdSl5JCc6IFwiJDFpZXNcIixcbiAgICAgICcoaGl2ZSkkJzogXCIkMXNcIixcbiAgICAgICcoPzooW15mXSlmZXwoW2xyXSlmKSQnOiBcIiQxJDJ2ZXNcIixcbiAgICAgICcoc2hlYXxsZWF8bG9hfHRoaWUpZiQnOiBcIiQxdmVzXCIsXG4gICAgICAnc2lzJCc6IFwic2VzXCIsXG4gICAgICAnKFt0aV0pdW0kJzogXCIkMWFcIixcbiAgICAgICcodG9tYXR8cG90YXR8ZWNofGhlcnx2ZXQpbyQnOiBcIiQxb2VzXCIsXG4gICAgICAnKGJ1KXMkJzogXCIkMXNlc1wiLFxuICAgICAgJyhhbGlhcykkJzogXCIkMWVzXCIsXG4gICAgICAnKG9jdG9wKXVzJCc6IFwiJDFpXCIsXG4gICAgICAnKGF4fHRlc3QpaXMkJzogXCIkMWVzXCIsXG4gICAgICAnKHVzKSQnOiBcIiQxZXNcIixcbiAgICAgICcoW15zXSspJCc6IFwiJDFzXCJcbiAgICB9XG4gICAgY29uc3QgaXJyZWd1bGFyOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgJ21vdmUnOiAnbW92ZXMnLFxuICAgICAgJ2Zvb3QnOiAnZmVldCcsXG4gICAgICAnZ29vc2UnOiAnZ2Vlc2UnLFxuICAgICAgJ3NleCc6ICdzZXhlcycsXG4gICAgICAnY2hpbGQnOiAnY2hpbGRyZW4nLFxuICAgICAgJ21hbic6ICdtZW4nLFxuICAgICAgJ3Rvb3RoJzogJ3RlZXRoJyxcbiAgICAgICdwZXJzb24nOiAncGVvcGxlJ1xuICAgIH1cbiAgICBjb25zdCB1bmNvdW50YWJsZTogc3RyaW5nW10gPSBbXG4gICAgICAnc2hlZXAnLFxuICAgICAgJ2Zpc2gnLFxuICAgICAgJ2RlZXInLFxuICAgICAgJ21vb3NlJyxcbiAgICAgICdzZXJpZXMnLFxuICAgICAgJ3NwZWNpZXMnLFxuICAgICAgJ21vbmV5JyxcbiAgICAgICdyaWNlJyxcbiAgICAgICdpbmZvcm1hdGlvbicsXG4gICAgICAnZXF1aXBtZW50JyxcbiAgICAgICdiaXNvbicsXG4gICAgICAnY29kJyxcbiAgICAgICdvZmZzcHJpbmcnLFxuICAgICAgJ3Bpa2UnLFxuICAgICAgJ3NhbG1vbicsXG4gICAgICAnc2hyaW1wJyxcbiAgICAgICdzd2luZScsXG4gICAgICAndHJvdXQnLFxuICAgICAgJ2FpcmNyYWZ0JyxcbiAgICAgICdob3ZlcmNyYWZ0JyxcbiAgICAgICdzcGFjZWNyYWZ0JyxcbiAgICAgICdzdWdhcicsXG4gICAgICAndHVuYScsXG4gICAgICAneW91JyxcbiAgICAgICd3b29kJ1xuICAgIF1cbiAgICAvLyBzYXZlIHNvbWUgdGltZSBpbiB0aGUgY2FzZSB0aGF0IHNpbmd1bGFyIGFuZCBwbHVyYWwgYXJlIHRoZSBzYW1lXG4gICAgaWYgKHVuY291bnRhYmxlLmluZGV4T2Yod29yZC50b0xvd2VyQ2FzZSgpKSA+PSAwKSB7XG4gICAgICByZXR1cm4gd29yZFxuICAgIH1cbiAgICAvLyBjaGVjayBmb3IgaXJyZWd1bGFyIGZvcm1zXG4gICAgZm9yIChjb25zdCB3IGluIGlycmVndWxhcikge1xuICAgICAgY29uc3QgcGF0dGVybiA9IG5ldyBSZWdFeHAoYCR7d30kYCwgJ2knKVxuICAgICAgY29uc3QgcmVwbGFjZSA9IGlycmVndWxhclt3XVxuICAgICAgaWYgKHBhdHRlcm4udGVzdCh3b3JkKSkge1xuICAgICAgICByZXR1cm4gd29yZC5yZXBsYWNlKHBhdHRlcm4sIHJlcGxhY2UpXG4gICAgICB9XG4gICAgfVxuICAgIC8vIGNoZWNrIGZvciBtYXRjaGVzIHVzaW5nIHJlZ3VsYXIgZXhwcmVzc2lvbnNcbiAgICBmb3IgKGNvbnN0IHJlZyBpbiBwbHVyYWwpIHtcbiAgICAgIGNvbnN0IHBhdHRlcm4gPSBuZXcgUmVnRXhwKHJlZywgJ2knKVxuICAgICAgaWYgKHBhdHRlcm4udGVzdCh3b3JkKSkge1xuICAgICAgICByZXR1cm4gd29yZC5yZXBsYWNlKHBhdHRlcm4sIHBsdXJhbFtyZWddKVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gd29yZFxuICB9XG5cblxuICAvKipcbiAgICogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzU3MTI5NzAzLzEzNDUxMDFcbiAgICpcbiAgKiBSZXR1cm5zIHRoZSBzaW5ndWxhciBvZiBhbiBFbmdsaXNoIHdvcmQuXG4gICpcbiAgKiBAZXhwb3J0XG4gICogQHBhcmFtIHtzdHJpbmd9IHdvcmRcbiAgKiBAcGFyYW0ge251bWJlcn0gW2Ftb3VudF1cbiAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAqL1xuICBzaW5ndWxhcih3b3JkOiBzdHJpbmcsIGFtb3VudD86IG51bWJlcik6IHN0cmluZyB7XG4gICAgaWYgKGFtb3VudCAhPT0gdW5kZWZpbmVkICYmIGFtb3VudCAhPT0gMSkge1xuICAgICAgcmV0dXJuIHdvcmRcbiAgICB9XG4gICAgY29uc3Qgc2luZ3VsYXI6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gICAgICAnKHF1aXopemVzJCc6IFwiJDFcIixcbiAgICAgICcobWF0cilpY2VzJCc6IFwiJDFpeFwiLFxuICAgICAgJyh2ZXJ0fGluZClpY2VzJCc6IFwiJDFleFwiLFxuICAgICAgJ14ob3gpZW4kJzogXCIkMVwiLFxuICAgICAgJyhhbGlhcyllcyQnOiBcIiQxXCIsXG4gICAgICAnKG9jdG9wfHZpcilpJCc6IFwiJDF1c1wiLFxuICAgICAgJyhjcmlzfGF4fHRlc3QpZXMkJzogXCIkMWlzXCIsXG4gICAgICAnKHNob2UpcyQnOiBcIiQxXCIsXG4gICAgICAnKG8pZXMkJzogXCIkMVwiLFxuICAgICAgJyhidXMpZXMkJzogXCIkMVwiLFxuICAgICAgJyhbbXxsXSlpY2UkJzogXCIkMW91c2VcIixcbiAgICAgICcoeHxjaHxzc3xzaCllcyQnOiBcIiQxXCIsXG4gICAgICAnKG0pb3ZpZXMkJzogXCIkMW92aWVcIixcbiAgICAgICcocyllcmllcyQnOiBcIiQxZXJpZXNcIixcbiAgICAgICcoW15hZWlvdXldfHF1KWllcyQnOiBcIiQxeVwiLFxuICAgICAgJyhbbHJdKXZlcyQnOiBcIiQxZlwiLFxuICAgICAgJyh0aXZlKXMkJzogXCIkMVwiLFxuICAgICAgJyhoaXZlKXMkJzogXCIkMVwiLFxuICAgICAgJyhsaXx3aXxrbmkpdmVzJCc6IFwiJDFmZVwiLFxuICAgICAgJyhzaGVhfGxvYXxsZWF8dGhpZSl2ZXMkJzogXCIkMWZcIixcbiAgICAgICcoXmFuYWx5KXNlcyQnOiBcIiQxc2lzXCIsXG4gICAgICAnKChhKW5hbHl8KGIpYXwoZClpYWdub3wocClhcmVudGhlfChwKXJvZ25vfChzKXlub3B8KHQpaGUpc2VzJCc6IFwiJDEkMnNpc1wiLFxuICAgICAgJyhbdGldKWEkJzogXCIkMXVtXCIsXG4gICAgICAnKG4pZXdzJCc6IFwiJDFld3NcIixcbiAgICAgICcoaHxibClvdXNlcyQnOiBcIiQxb3VzZVwiLFxuICAgICAgJyhjb3Jwc2UpcyQnOiBcIiQxXCIsXG4gICAgICAnKHVzKWVzJCc6IFwiJDFcIixcbiAgICAgICdzJCc6IFwiXCJcbiAgICB9XG4gICAgY29uc3QgaXJyZWd1bGFyOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9ID0ge1xuICAgICAgJ21vdmUnOiAnbW92ZXMnLFxuICAgICAgJ2Zvb3QnOiAnZmVldCcsXG4gICAgICAnZ29vc2UnOiAnZ2Vlc2UnLFxuICAgICAgJ3NleCc6ICdzZXhlcycsXG4gICAgICAnY2hpbGQnOiAnY2hpbGRyZW4nLFxuICAgICAgJ21hbic6ICdtZW4nLFxuICAgICAgJ3Rvb3RoJzogJ3RlZXRoJyxcbiAgICAgICdwZXJzb24nOiAncGVvcGxlJ1xuICAgIH1cbiAgICBjb25zdCB1bmNvdW50YWJsZTogc3RyaW5nW10gPSBbXG4gICAgICAnc2hlZXAnLFxuICAgICAgJ2Zpc2gnLFxuICAgICAgJ2RlZXInLFxuICAgICAgJ21vb3NlJyxcbiAgICAgICdzZXJpZXMnLFxuICAgICAgJ3NwZWNpZXMnLFxuICAgICAgJ21vbmV5JyxcbiAgICAgICdyaWNlJyxcbiAgICAgICdpbmZvcm1hdGlvbicsXG4gICAgICAnZXF1aXBtZW50JyxcbiAgICAgICdiaXNvbicsXG4gICAgICAnY29kJyxcbiAgICAgICdvZmZzcHJpbmcnLFxuICAgICAgJ3Bpa2UnLFxuICAgICAgJ3NhbG1vbicsXG4gICAgICAnc2hyaW1wJyxcbiAgICAgICdzd2luZScsXG4gICAgICAndHJvdXQnLFxuICAgICAgJ2FpcmNyYWZ0JyxcbiAgICAgICdob3ZlcmNyYWZ0JyxcbiAgICAgICdzcGFjZWNyYWZ0JyxcbiAgICAgICdzdWdhcicsXG4gICAgICAndHVuYScsXG4gICAgICAneW91JyxcbiAgICAgICd3b29kJ1xuICAgIF1cbiAgICAvLyBzYXZlIHNvbWUgdGltZSBpbiB0aGUgY2FzZSB0aGF0IHNpbmd1bGFyIGFuZCBwbHVyYWwgYXJlIHRoZSBzYW1lXG4gICAgaWYgKHVuY291bnRhYmxlLmluZGV4T2Yod29yZC50b0xvd2VyQ2FzZSgpKSA+PSAwKSB7XG4gICAgICByZXR1cm4gd29yZFxuICAgIH1cbiAgICAvLyBjaGVjayBmb3IgaXJyZWd1bGFyIGZvcm1zXG4gICAgZm9yIChjb25zdCB3IGluIGlycmVndWxhcikge1xuICAgICAgY29uc3QgcGF0dGVybiA9IG5ldyBSZWdFeHAoYCR7aXJyZWd1bGFyW3ddfSRgLCAnaScpXG4gICAgICBjb25zdCByZXBsYWNlID0gd1xuICAgICAgaWYgKHBhdHRlcm4udGVzdCh3b3JkKSkge1xuICAgICAgICByZXR1cm4gd29yZC5yZXBsYWNlKHBhdHRlcm4sIHJlcGxhY2UpXG4gICAgICB9XG4gICAgfVxuICAgIC8vIGNoZWNrIGZvciBtYXRjaGVzIHVzaW5nIHJlZ3VsYXIgZXhwcmVzc2lvbnNcbiAgICBmb3IgKGNvbnN0IHJlZyBpbiBzaW5ndWxhcikge1xuICAgICAgY29uc3QgcGF0dGVybiA9IG5ldyBSZWdFeHAocmVnLCAnaScpXG4gICAgICBpZiAocGF0dGVybi50ZXN0KHdvcmQpKSB7XG4gICAgICAgIHJldHVybiB3b3JkLnJlcGxhY2UocGF0dGVybiwgc2luZ3VsYXJbcmVnXSlcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHdvcmRcbiAgfVxuXG59XG5cbiJdfQ==