react-native-divkit 0.1.0-alpha.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 (322) hide show
  1. package/LICENSE +176 -0
  2. package/README.md +340 -0
  3. package/dist/DivKit.d.ts +68 -0
  4. package/dist/DivKit.d.ts.map +1 -0
  5. package/dist/DivKit.js +400 -0
  6. package/dist/DivKit.js.map +1 -0
  7. package/dist/actions/array.d.ts +8 -0
  8. package/dist/actions/array.d.ts.map +1 -0
  9. package/dist/actions/array.js +139 -0
  10. package/dist/actions/array.js.map +1 -0
  11. package/dist/actions/copyToClipboard.d.ts +22 -0
  12. package/dist/actions/copyToClipboard.d.ts.map +1 -0
  13. package/dist/actions/copyToClipboard.js +63 -0
  14. package/dist/actions/copyToClipboard.js.map +1 -0
  15. package/dist/actions/dict.d.ts +6 -0
  16. package/dist/actions/dict.d.ts.map +1 -0
  17. package/dist/actions/dict.js +58 -0
  18. package/dist/actions/dict.js.map +1 -0
  19. package/dist/actions/index.d.ts +11 -0
  20. package/dist/actions/index.d.ts.map +1 -0
  21. package/dist/actions/index.js +11 -0
  22. package/dist/actions/index.js.map +1 -0
  23. package/dist/actions/updateStructure.d.ts +6 -0
  24. package/dist/actions/updateStructure.d.ts.map +1 -0
  25. package/dist/actions/updateStructure.js +116 -0
  26. package/dist/actions/updateStructure.js.map +1 -0
  27. package/dist/components/DivComponent.d.ts +29 -0
  28. package/dist/components/DivComponent.d.ts.map +1 -0
  29. package/dist/components/DivComponent.js +62 -0
  30. package/dist/components/DivComponent.js.map +1 -0
  31. package/dist/components/container/DivContainer.d.ts +26 -0
  32. package/dist/components/container/DivContainer.d.ts.map +1 -0
  33. package/dist/components/container/DivContainer.js +172 -0
  34. package/dist/components/container/DivContainer.js.map +1 -0
  35. package/dist/components/container/index.d.ts +3 -0
  36. package/dist/components/container/index.d.ts.map +1 -0
  37. package/dist/components/container/index.js +2 -0
  38. package/dist/components/container/index.js.map +1 -0
  39. package/dist/components/image/DivImage.d.ts +29 -0
  40. package/dist/components/image/DivImage.d.ts.map +1 -0
  41. package/dist/components/image/DivImage.js +122 -0
  42. package/dist/components/image/DivImage.js.map +1 -0
  43. package/dist/components/image/index.d.ts +3 -0
  44. package/dist/components/image/index.d.ts.map +1 -0
  45. package/dist/components/image/index.js +2 -0
  46. package/dist/components/image/index.js.map +1 -0
  47. package/dist/components/index.d.ts +14 -0
  48. package/dist/components/index.d.ts.map +1 -0
  49. package/dist/components/index.js +11 -0
  50. package/dist/components/index.js.map +1 -0
  51. package/dist/components/state/DivState.d.ts +26 -0
  52. package/dist/components/state/DivState.d.ts.map +1 -0
  53. package/dist/components/state/DivState.js +121 -0
  54. package/dist/components/state/DivState.js.map +1 -0
  55. package/dist/components/state/index.d.ts +3 -0
  56. package/dist/components/state/index.d.ts.map +1 -0
  57. package/dist/components/state/index.js +2 -0
  58. package/dist/components/state/index.js.map +1 -0
  59. package/dist/components/text/DivText.d.ts +28 -0
  60. package/dist/components/text/DivText.d.ts.map +1 -0
  61. package/dist/components/text/DivText.js +143 -0
  62. package/dist/components/text/DivText.js.map +1 -0
  63. package/dist/components/text/index.d.ts +3 -0
  64. package/dist/components/text/index.d.ts.map +1 -0
  65. package/dist/components/text/index.js +2 -0
  66. package/dist/components/text/index.js.map +1 -0
  67. package/dist/components/utilities/Outer.d.ts +17 -0
  68. package/dist/components/utilities/Outer.d.ts.map +1 -0
  69. package/dist/components/utilities/Outer.js +210 -0
  70. package/dist/components/utilities/Outer.js.map +1 -0
  71. package/dist/components/utilities/Unknown.d.ts +11 -0
  72. package/dist/components/utilities/Unknown.d.ts.map +1 -0
  73. package/dist/components/utilities/Unknown.js +50 -0
  74. package/dist/components/utilities/Unknown.js.map +1 -0
  75. package/dist/components/utilities/index.d.ts +5 -0
  76. package/dist/components/utilities/index.d.ts.map +1 -0
  77. package/dist/components/utilities/index.js +3 -0
  78. package/dist/components/utilities/index.js.map +1 -0
  79. package/dist/context/ActionContext.d.ts +25 -0
  80. package/dist/context/ActionContext.d.ts.map +1 -0
  81. package/dist/context/ActionContext.js +20 -0
  82. package/dist/context/ActionContext.js.map +1 -0
  83. package/dist/context/DivKitContext.d.ts +33 -0
  84. package/dist/context/DivKitContext.d.ts.map +1 -0
  85. package/dist/context/DivKitContext.js +14 -0
  86. package/dist/context/DivKitContext.js.map +1 -0
  87. package/dist/context/EnabledContext.d.ts +31 -0
  88. package/dist/context/EnabledContext.d.ts.map +1 -0
  89. package/dist/context/EnabledContext.js +31 -0
  90. package/dist/context/EnabledContext.js.map +1 -0
  91. package/dist/context/StateContext.d.ts +57 -0
  92. package/dist/context/StateContext.d.ts.map +1 -0
  93. package/dist/context/StateContext.js +20 -0
  94. package/dist/context/StateContext.js.map +1 -0
  95. package/dist/context/index.d.ts +9 -0
  96. package/dist/context/index.d.ts.map +1 -0
  97. package/dist/context/index.js +9 -0
  98. package/dist/context/index.js.map +1 -0
  99. package/dist/expressions/bigint.d.ts +8 -0
  100. package/dist/expressions/bigint.d.ts.map +1 -0
  101. package/dist/expressions/bigint.js +31 -0
  102. package/dist/expressions/bigint.js.map +1 -0
  103. package/dist/expressions/const.d.ts +15 -0
  104. package/dist/expressions/const.d.ts.map +1 -0
  105. package/dist/expressions/const.js +15 -0
  106. package/dist/expressions/const.js.map +1 -0
  107. package/dist/expressions/eval.d.ts +77 -0
  108. package/dist/expressions/eval.d.ts.map +1 -0
  109. package/dist/expressions/eval.js +459 -0
  110. package/dist/expressions/eval.js.map +1 -0
  111. package/dist/expressions/expressions.d.ts +7 -0
  112. package/dist/expressions/expressions.d.ts.map +1 -0
  113. package/dist/expressions/expressions.js +3191 -0
  114. package/dist/expressions/expressions.js.map +1 -0
  115. package/dist/expressions/funcs/array.d.ts +2 -0
  116. package/dist/expressions/funcs/array.d.ts.map +1 -0
  117. package/dist/expressions/funcs/array.js +381 -0
  118. package/dist/expressions/funcs/array.js.map +1 -0
  119. package/dist/expressions/funcs/colors.d.ts +2 -0
  120. package/dist/expressions/funcs/colors.d.ts.map +1 -0
  121. package/dist/expressions/funcs/colors.js +75 -0
  122. package/dist/expressions/funcs/colors.js.map +1 -0
  123. package/dist/expressions/funcs/customFuncs.d.ts +8 -0
  124. package/dist/expressions/funcs/customFuncs.d.ts.map +1 -0
  125. package/dist/expressions/funcs/customFuncs.js +114 -0
  126. package/dist/expressions/funcs/customFuncs.js.map +1 -0
  127. package/dist/expressions/funcs/datetime.d.ts +2 -0
  128. package/dist/expressions/funcs/datetime.d.ts.map +1 -0
  129. package/dist/expressions/funcs/datetime.js +182 -0
  130. package/dist/expressions/funcs/datetime.js.map +1 -0
  131. package/dist/expressions/funcs/dict.d.ts +2 -0
  132. package/dist/expressions/funcs/dict.d.ts.map +1 -0
  133. package/dist/expressions/funcs/dict.js +170 -0
  134. package/dist/expressions/funcs/dict.js.map +1 -0
  135. package/dist/expressions/funcs/funcs.d.ts +80 -0
  136. package/dist/expressions/funcs/funcs.d.ts.map +1 -0
  137. package/dist/expressions/funcs/funcs.js +146 -0
  138. package/dist/expressions/funcs/funcs.js.map +1 -0
  139. package/dist/expressions/funcs/index.d.ts +2 -0
  140. package/dist/expressions/funcs/index.d.ts.map +1 -0
  141. package/dist/expressions/funcs/index.js +23 -0
  142. package/dist/expressions/funcs/index.js.map +1 -0
  143. package/dist/expressions/funcs/interval.d.ts +2 -0
  144. package/dist/expressions/funcs/interval.d.ts.map +1 -0
  145. package/dist/expressions/funcs/interval.js +61 -0
  146. package/dist/expressions/funcs/interval.js.map +1 -0
  147. package/dist/expressions/funcs/math.d.ts +2 -0
  148. package/dist/expressions/funcs/math.d.ts.map +1 -0
  149. package/dist/expressions/funcs/math.js +324 -0
  150. package/dist/expressions/funcs/math.js.map +1 -0
  151. package/dist/expressions/funcs/std.d.ts +2 -0
  152. package/dist/expressions/funcs/std.d.ts.map +1 -0
  153. package/dist/expressions/funcs/std.js +293 -0
  154. package/dist/expressions/funcs/std.js.map +1 -0
  155. package/dist/expressions/funcs/stored.d.ts +4 -0
  156. package/dist/expressions/funcs/stored.d.ts.map +1 -0
  157. package/dist/expressions/funcs/stored.js +62 -0
  158. package/dist/expressions/funcs/stored.js.map +1 -0
  159. package/dist/expressions/funcs/strings.d.ts +2 -0
  160. package/dist/expressions/funcs/strings.d.ts.map +1 -0
  161. package/dist/expressions/funcs/strings.js +158 -0
  162. package/dist/expressions/funcs/strings.js.map +1 -0
  163. package/dist/expressions/funcs/trigonometry.d.ts +2 -0
  164. package/dist/expressions/funcs/trigonometry.d.ts.map +1 -0
  165. package/dist/expressions/funcs/trigonometry.js +92 -0
  166. package/dist/expressions/funcs/trigonometry.js.map +1 -0
  167. package/dist/expressions/json.d.ts +18 -0
  168. package/dist/expressions/json.d.ts.map +1 -0
  169. package/dist/expressions/json.js +271 -0
  170. package/dist/expressions/json.js.map +1 -0
  171. package/dist/expressions/parserCache.d.ts +4 -0
  172. package/dist/expressions/parserCache.d.ts.map +1 -0
  173. package/dist/expressions/parserCache.js +23 -0
  174. package/dist/expressions/parserCache.js.map +1 -0
  175. package/dist/expressions/simpleUnescapeString.d.ts +2 -0
  176. package/dist/expressions/simpleUnescapeString.d.ts.map +1 -0
  177. package/dist/expressions/simpleUnescapeString.js +61 -0
  178. package/dist/expressions/simpleUnescapeString.js.map +1 -0
  179. package/dist/expressions/utils.d.ts +29 -0
  180. package/dist/expressions/utils.d.ts.map +1 -0
  181. package/dist/expressions/utils.js +236 -0
  182. package/dist/expressions/utils.js.map +1 -0
  183. package/dist/expressions/variable.d.ts +82 -0
  184. package/dist/expressions/variable.d.ts.map +1 -0
  185. package/dist/expressions/variable.js +337 -0
  186. package/dist/expressions/variable.js.map +1 -0
  187. package/dist/expressions/walk.d.ts +7 -0
  188. package/dist/expressions/walk.d.ts.map +1 -0
  189. package/dist/expressions/walk.js +39 -0
  190. package/dist/expressions/walk.js.map +1 -0
  191. package/dist/hooks/index.d.ts +8 -0
  192. package/dist/hooks/index.d.ts.map +1 -0
  193. package/dist/hooks/index.js +11 -0
  194. package/dist/hooks/index.js.map +1 -0
  195. package/dist/hooks/useAction.d.ts +102 -0
  196. package/dist/hooks/useAction.d.ts.map +1 -0
  197. package/dist/hooks/useAction.js +116 -0
  198. package/dist/hooks/useAction.js.map +1 -0
  199. package/dist/hooks/useDerivedFromVars.d.ts +72 -0
  200. package/dist/hooks/useDerivedFromVars.d.ts.map +1 -0
  201. package/dist/hooks/useDerivedFromVars.js +100 -0
  202. package/dist/hooks/useDerivedFromVars.js.map +1 -0
  203. package/dist/hooks/useVariable.d.ts +86 -0
  204. package/dist/hooks/useVariable.d.ts.map +1 -0
  205. package/dist/hooks/useVariable.js +130 -0
  206. package/dist/hooks/useVariable.js.map +1 -0
  207. package/dist/index.d.ts +30 -0
  208. package/dist/index.d.ts.map +1 -0
  209. package/dist/index.js +28 -0
  210. package/dist/index.js.map +1 -0
  211. package/dist/stores/createObservable.d.ts +38 -0
  212. package/dist/stores/createObservable.d.ts.map +1 -0
  213. package/dist/stores/createObservable.js +49 -0
  214. package/dist/stores/createObservable.js.map +1 -0
  215. package/dist/utils/applyTemplate.d.ts +8 -0
  216. package/dist/utils/applyTemplate.d.ts.map +1 -0
  217. package/dist/utils/applyTemplate.js +94 -0
  218. package/dist/utils/applyTemplate.js.map +1 -0
  219. package/dist/utils/correctColor.d.ts +18 -0
  220. package/dist/utils/correctColor.d.ts.map +1 -0
  221. package/dist/utils/correctColor.js +79 -0
  222. package/dist/utils/correctColor.js.map +1 -0
  223. package/dist/utils/escapeRegExp.d.ts +2 -0
  224. package/dist/utils/escapeRegExp.d.ts.map +1 -0
  225. package/dist/utils/escapeRegExp.js +4 -0
  226. package/dist/utils/escapeRegExp.js.map +1 -0
  227. package/dist/utils/formatDate.d.ts +6 -0
  228. package/dist/utils/formatDate.d.ts.map +1 -0
  229. package/dist/utils/formatDate.js +325 -0
  230. package/dist/utils/formatDate.js.map +1 -0
  231. package/dist/utils/padLeft.d.ts +2 -0
  232. package/dist/utils/padLeft.d.ts.map +1 -0
  233. package/dist/utils/padLeft.js +7 -0
  234. package/dist/utils/padLeft.js.map +1 -0
  235. package/dist/utils/uniq.d.ts +2 -0
  236. package/dist/utils/uniq.d.ts.map +1 -0
  237. package/dist/utils/uniq.js +4 -0
  238. package/dist/utils/uniq.js.map +1 -0
  239. package/dist/utils/wrapError.d.ts +10 -0
  240. package/dist/utils/wrapError.d.ts.map +1 -0
  241. package/dist/utils/wrapError.js +9 -0
  242. package/dist/utils/wrapError.js.map +1 -0
  243. package/package.json +58 -0
  244. package/src/DivKit.tsx +542 -0
  245. package/src/actions/array.ts +170 -0
  246. package/src/actions/copyToClipboard.ts +82 -0
  247. package/src/actions/dict.ts +71 -0
  248. package/src/actions/index.ts +11 -0
  249. package/src/actions/updateStructure.ts +134 -0
  250. package/src/components/DivComponent.tsx +75 -0
  251. package/src/components/README.md +230 -0
  252. package/src/components/container/DivContainer.tsx +222 -0
  253. package/src/components/container/index.ts +2 -0
  254. package/src/components/image/DivImage.tsx +172 -0
  255. package/src/components/image/index.ts +2 -0
  256. package/src/components/index.ts +20 -0
  257. package/src/components/state/DivState.tsx +146 -0
  258. package/src/components/state/index.ts +2 -0
  259. package/src/components/text/DivText.tsx +186 -0
  260. package/src/components/text/index.ts +2 -0
  261. package/src/components/utilities/Outer.tsx +239 -0
  262. package/src/components/utilities/README.md +175 -0
  263. package/src/components/utilities/Unknown.tsx +60 -0
  264. package/src/components/utilities/index.ts +4 -0
  265. package/src/context/ActionContext.tsx +37 -0
  266. package/src/context/DivKitContext.tsx +54 -0
  267. package/src/context/EnabledContext.tsx +50 -0
  268. package/src/context/StateContext.tsx +75 -0
  269. package/src/context/index.ts +33 -0
  270. package/src/expressions/ast.d.ts +101 -0
  271. package/src/expressions/bigint.ts +38 -0
  272. package/src/expressions/const.ts +16 -0
  273. package/src/expressions/eval.ts +669 -0
  274. package/src/expressions/expressions.peggy +235 -0
  275. package/src/expressions/expressions.ts +2854 -0
  276. package/src/expressions/funcs/array.ts +412 -0
  277. package/src/expressions/funcs/colors.ts +100 -0
  278. package/src/expressions/funcs/customFuncs.ts +139 -0
  279. package/src/expressions/funcs/datetime.ts +232 -0
  280. package/src/expressions/funcs/dict.ts +207 -0
  281. package/src/expressions/funcs/funcs.ts +323 -0
  282. package/src/expressions/funcs/index.ts +23 -0
  283. package/src/expressions/funcs/interval.ts +76 -0
  284. package/src/expressions/funcs/math.ts +395 -0
  285. package/src/expressions/funcs/std.ts +392 -0
  286. package/src/expressions/funcs/stored.ts +62 -0
  287. package/src/expressions/funcs/strings.ts +200 -0
  288. package/src/expressions/funcs/trigonometry.ts +108 -0
  289. package/src/expressions/json.ts +367 -0
  290. package/src/expressions/parserCache.ts +32 -0
  291. package/src/expressions/simpleUnescapeString.ts +57 -0
  292. package/src/expressions/utils.ts +271 -0
  293. package/src/expressions/variable.ts +429 -0
  294. package/src/expressions/walk.ts +43 -0
  295. package/src/hooks/README.md +265 -0
  296. package/src/hooks/index.ts +28 -0
  297. package/src/hooks/useAction.ts +152 -0
  298. package/src/hooks/useDerivedFromVars.ts +187 -0
  299. package/src/hooks/useVariable.ts +157 -0
  300. package/src/index.ts +97 -0
  301. package/src/stores/createObservable.ts +64 -0
  302. package/src/types/alignment.d.ts +13 -0
  303. package/src/types/background.d.ts +71 -0
  304. package/src/types/base.d.ts +224 -0
  305. package/src/types/border.d.ts +46 -0
  306. package/src/types/componentContext.d.ts +98 -0
  307. package/src/types/container.d.ts +40 -0
  308. package/src/types/edgeInserts.d.ts +9 -0
  309. package/src/types/general.d.ts +3 -0
  310. package/src/types/image.d.ts +33 -0
  311. package/src/types/imageScale.d.ts +1 -0
  312. package/src/types/layoutParams.d.ts +27 -0
  313. package/src/types/sizes.d.ts +37 -0
  314. package/src/types/state.d.ts +19 -0
  315. package/src/types/text.d.ts +126 -0
  316. package/src/utils/applyTemplate.ts +145 -0
  317. package/src/utils/correctColor.ts +102 -0
  318. package/src/utils/escapeRegExp.ts +3 -0
  319. package/src/utils/formatDate.ts +385 -0
  320. package/src/utils/padLeft.ts +6 -0
  321. package/src/utils/uniq.ts +3 -0
  322. package/src/utils/wrapError.ts +21 -0
@@ -0,0 +1,108 @@
1
+ import type { EvalContext, EvalValue, NumberValue } from '../eval';
2
+ import { registerFunc } from './funcs';
3
+ import { NUMBER } from '../const';
4
+
5
+ function pi(): EvalValue {
6
+ return {
7
+ type: NUMBER,
8
+ value: Math.PI
9
+ };
10
+ }
11
+
12
+ function toRadians(_ctx: EvalContext, degrees: NumberValue): EvalValue {
13
+ return {
14
+ type: NUMBER,
15
+ value: degrees.value / 180 * Math.PI
16
+ };
17
+ }
18
+
19
+ function toDegrees(_ctx: EvalContext, radians: NumberValue): EvalValue {
20
+ return {
21
+ type: NUMBER,
22
+ value: radians.value / Math.PI * 180
23
+ };
24
+ }
25
+
26
+ function sin(_ctx: EvalContext, rad: NumberValue): EvalValue {
27
+ return {
28
+ type: NUMBER,
29
+ value: Math.sin(rad.value)
30
+ };
31
+ }
32
+
33
+ function cos(_ctx: EvalContext, rad: NumberValue): EvalValue {
34
+ return {
35
+ type: NUMBER,
36
+ value: Math.cos(rad.value)
37
+ };
38
+ }
39
+
40
+ function tan(_ctx: EvalContext, rad: NumberValue): EvalValue {
41
+ return {
42
+ type: NUMBER,
43
+ value: Math.tan(rad.value)
44
+ };
45
+ }
46
+
47
+ function cot(_ctx: EvalContext, rad: NumberValue): EvalValue {
48
+ const tan = Math.tan(rad.value);
49
+
50
+ if (Math.abs(tan) < 1e-12) {
51
+ throw new Error('Cotangent is undefined for the given value.');
52
+ }
53
+
54
+ return {
55
+ type: NUMBER,
56
+ value: 1 / tan
57
+ };
58
+ }
59
+
60
+ function atan(_ctx: EvalContext, rad: NumberValue): EvalValue {
61
+ return {
62
+ type: NUMBER,
63
+ value: Math.atan(rad.value)
64
+ };
65
+ }
66
+
67
+ function atan2(_ctx: EvalContext, y: NumberValue, x: NumberValue): EvalValue {
68
+ return {
69
+ type: NUMBER,
70
+ value: Math.atan2(y.value, x.value)
71
+ };
72
+ }
73
+
74
+ function asin(_ctx: EvalContext, rad: NumberValue): EvalValue {
75
+ if (rad.value > 1 || rad.value < -1) {
76
+ throw new Error('Arcsine is undefined for the given value.');
77
+ }
78
+
79
+ return {
80
+ type: NUMBER,
81
+ value: Math.asin(rad.value)
82
+ };
83
+ }
84
+
85
+ function acos(_ctx: EvalContext, rad: NumberValue): EvalValue {
86
+ if (rad.value > 1 || rad.value < -1) {
87
+ throw new Error('Arccosine is undefined for the given value.');
88
+ }
89
+
90
+ return {
91
+ type: NUMBER,
92
+ value: Math.acos(rad.value)
93
+ };
94
+ }
95
+
96
+ export function registerTrigonometry(): void {
97
+ registerFunc('pi', [], pi);
98
+ registerFunc('toRadians', [NUMBER], toRadians);
99
+ registerFunc('toDegrees', [NUMBER], toDegrees);
100
+ registerFunc('sin', [NUMBER], sin);
101
+ registerFunc('cos', [NUMBER], cos);
102
+ registerFunc('tan', [NUMBER], tan);
103
+ registerFunc('cot', [NUMBER], cot);
104
+ registerFunc('atan', [NUMBER], atan);
105
+ registerFunc('atan2', [NUMBER, NUMBER], atan2);
106
+ registerFunc('asin', [NUMBER], asin);
107
+ registerFunc('acos', [NUMBER], acos);
108
+ }
@@ -0,0 +1,367 @@
1
+ /* eslint-disable max-depth */
2
+ import type { Node } from './ast';
3
+ import type { Variable, VariableValue } from './variable';
4
+ import type { Store } from '../../typings/store';
5
+ import { uniq } from '../utils/uniq';
6
+ import { parse } from './expressions';
7
+ import { evalExpression, type VariablesMap } from './eval';
8
+ import { dateToString, gatherVarsFromAst, stringifyColor } from './utils';
9
+ import { type LogError, wrapError } from '../utils/wrapError';
10
+ import { parseColor } from '../utils/correctColor';
11
+ import { MAX_INT32, MIN_INT32 } from './const';
12
+ import { simpleUnescapeString } from './simpleUnescapeString';
13
+ import { cacheGet, cacheSet } from './parserCache';
14
+ import type { CustomFunctions } from './funcs/customFuncs';
15
+
16
+ class ExpressionBinding {
17
+ private readonly ast: Node;
18
+ private readonly expr: string;
19
+
20
+ constructor(ast: Node, expr: string) {
21
+ this.ast = ast;
22
+ this.expr = expr;
23
+ }
24
+
25
+ /**
26
+ * Applies variables into ast
27
+ * @param variables
28
+ * @param logError
29
+ */
30
+ apply<T>(
31
+ {
32
+ variables,
33
+ customFunctions,
34
+ logError,
35
+ store,
36
+ weekStartDay,
37
+ keepComplex
38
+ }: {
39
+ variables: VariablesMap;
40
+ customFunctions: CustomFunctions | undefined;
41
+ logError: LogError;
42
+ store: Store | undefined;
43
+ weekStartDay: number;
44
+ keepComplex?: boolean;
45
+ }
46
+ ): {
47
+ result: T;
48
+ usedVars?: Set<Variable>;
49
+ } {
50
+ let res: ReturnType<typeof evalExpression> | undefined;
51
+
52
+ try {
53
+ res = evalExpression(variables, customFunctions, store, this.ast, {
54
+ weekStartDay
55
+ });
56
+ res.warnings.forEach(logError);
57
+ const result = res.result;
58
+
59
+ if (result.type === 'error') {
60
+ logError(wrapError(new Error('Expression execution error'), {
61
+ additional: {
62
+ message: result.value,
63
+ expression: this.expr
64
+ }
65
+ }));
66
+ return {
67
+ result: undefined as T,
68
+ usedVars: res.usedVars
69
+ };
70
+ }
71
+
72
+ const value = result.value;
73
+ if (value instanceof Date) {
74
+ return {
75
+ result: dateToString(value) as T,
76
+ usedVars: res.usedVars
77
+ };
78
+ }
79
+ if (result.type === 'boolean') {
80
+ return {
81
+ result: Boolean(value) as T,
82
+ usedVars: res.usedVars
83
+ };
84
+ }
85
+ if (result.type === 'color') {
86
+ const parsed = parseColor(String(value));
87
+ if (parsed) {
88
+ return {
89
+ result: stringifyColor(parsed) as T,
90
+ usedVars: res.usedVars
91
+ };
92
+ }
93
+ logError(wrapError(new Error('Expression execution error')));
94
+ }
95
+ if (result.type === 'integer') {
96
+ if ((value as number) > MAX_INT32 || (value as number) < MIN_INT32) {
97
+ logError(wrapError(new Error('Expression result is out of 32-bit int range')));
98
+ return {
99
+ result: undefined as T,
100
+ usedVars: res.usedVars
101
+ };
102
+ }
103
+ return {
104
+ result: Number(value) as T,
105
+ usedVars: res.usedVars
106
+ };
107
+ }
108
+ if (result.type === 'function') {
109
+ return {
110
+ result: `<${result.value[0]?.name || 'Function'}>` as T,
111
+ usedVars: res.usedVars
112
+ };
113
+ }
114
+ if (!keepComplex && (result.type === 'array' || result.type === 'dict')) {
115
+ try {
116
+ return {
117
+ result: JSON.stringify(value) as T,
118
+ usedVars: res.usedVars
119
+ };
120
+ } catch (err) {
121
+ logError(wrapError(new Error(`Failed to stringify ${result.type}`)));
122
+ return {
123
+ result: `<${result.type}>` as T,
124
+ usedVars: res.usedVars
125
+ };
126
+ }
127
+ }
128
+ return {
129
+ result: value as T,
130
+ usedVars: res.usedVars
131
+ };
132
+ } catch (err) {
133
+ logError(wrapError(new Error('Expression execution error'), {
134
+ additional: {
135
+ expression: this.expr
136
+ }
137
+ }));
138
+ return {
139
+ result: undefined as T,
140
+ usedVars: res?.usedVars
141
+ };
142
+ }
143
+ }
144
+ }
145
+
146
+ class VariableBinding {
147
+ private readonly variable: string;
148
+
149
+ constructor(variable: string) {
150
+ this.variable = variable;
151
+ }
152
+
153
+ /**
154
+ * Applies variables into ast
155
+ * @param variables
156
+ * @param logError
157
+ */
158
+ apply(variables: VariablesMap): VariableValue | string | undefined {
159
+ const varInstance = variables.get(this.variable);
160
+ if (varInstance) {
161
+ return varInstance.getValue();
162
+ }
163
+
164
+ return undefined;
165
+ }
166
+ }
167
+
168
+ export type MaybeMissing<T> = T | (
169
+ T extends (infer U)[] ?
170
+ MaybeMissing<U>[] :
171
+ (
172
+ T extends object ?
173
+ {
174
+ [P in keyof T]?: MaybeMissing<T[P]>;
175
+ } :
176
+ T | undefined
177
+ )
178
+ );
179
+
180
+ function hasExpressions(str: string): boolean {
181
+ return str.indexOf('@{') > -1 || str.indexOf('\\') > -1;
182
+ }
183
+
184
+ function prepareVarsObj<T>(
185
+ jsonProp: T,
186
+ store: {
187
+ vars: string[];
188
+ hasExpression: boolean;
189
+ },
190
+ logError: LogError,
191
+ maxDepth: number
192
+ ): unknown {
193
+ if (jsonProp) {
194
+ if (typeof jsonProp === 'string') {
195
+ if (hasExpressions(jsonProp)) {
196
+ store.hasExpression = true;
197
+
198
+ if (process.env.ENABLE_EXPRESSIONS || process.env.ENABLE_EXPRESSIONS === undefined) {
199
+ try {
200
+ const ast = cacheGet(jsonProp) || parse(jsonProp, {
201
+ startRule: 'JsonStringContents'
202
+ });
203
+ cacheSet(jsonProp, ast);
204
+ const propVars = gatherVarsFromAst(ast);
205
+ store.vars.push(...propVars);
206
+
207
+ return new ExpressionBinding(ast, jsonProp);
208
+ } catch (err) {
209
+ logError(wrapError(new Error('Unable to parse expression'), {
210
+ additional: {
211
+ expression: jsonProp
212
+ }
213
+ }));
214
+ return undefined;
215
+ }
216
+ } else {
217
+ if (jsonProp === '@{}') {
218
+ return '';
219
+ } else if (jsonProp.startsWith('@{') && jsonProp.endsWith('}')) {
220
+ return new VariableBinding(jsonProp.substring(2, jsonProp.length - 1));
221
+ }
222
+ try {
223
+ return simpleUnescapeString(jsonProp);
224
+ } catch (err: any) {
225
+ logError(wrapError(err as Error, {
226
+ additional: {
227
+ expression: jsonProp
228
+ }
229
+ }));
230
+ return undefined;
231
+ }
232
+ }
233
+ }
234
+ } else if (Array.isArray(jsonProp) && maxDepth > 0) {
235
+ return jsonProp.map(item => prepareVarsObj(item, store, logError, maxDepth - 1));
236
+ } else if (typeof jsonProp === 'object' && maxDepth > 0) {
237
+ const res: Record<string, unknown> = {};
238
+ for (const key in jsonProp) {
239
+ res[key] = prepareVarsObj(jsonProp[key], store, logError, maxDepth - 1);
240
+ }
241
+ return res;
242
+ }
243
+ }
244
+ return jsonProp;
245
+ }
246
+
247
+ function applyVars<T>(
248
+ jsonProp: T,
249
+ opts: {
250
+ variables: VariablesMap;
251
+ customFunctions: CustomFunctions | undefined;
252
+ logError: LogError;
253
+ store: Store | undefined;
254
+ weekStartDay: number;
255
+ keepComplex?: boolean;
256
+ }
257
+ ): {
258
+ result: MaybeMissing<T>;
259
+ usedVars?: Set<Variable>;
260
+ } {
261
+ if (jsonProp) {
262
+ if (
263
+ (process.env.ENABLE_EXPRESSIONS || process.env.ENABLE_EXPRESSIONS === undefined) &&
264
+ jsonProp instanceof ExpressionBinding
265
+ ) {
266
+ return jsonProp.apply<T>(opts);
267
+ } else if (
268
+ (!process.env.ENABLE_EXPRESSIONS && process.env.ENABLE_EXPRESSIONS !== undefined) &&
269
+ jsonProp instanceof VariableBinding
270
+ ) {
271
+ return {
272
+ result: jsonProp.apply(opts.variables) as T
273
+ };
274
+ } else if (Array.isArray(jsonProp)) {
275
+ let usedVars: Set<Variable> | undefined;
276
+ const arr = jsonProp.map(it => {
277
+ const subres = applyVars(it, opts);
278
+
279
+ if (subres.usedVars) {
280
+ if (!usedVars) {
281
+ usedVars = new Set();
282
+ }
283
+ for (const instance of subres.usedVars) {
284
+ usedVars.add(instance);
285
+ }
286
+ }
287
+
288
+ return subres.result;
289
+ });
290
+
291
+ return {
292
+ result: arr as MaybeMissing<T>,
293
+ usedVars
294
+ };
295
+ } else if (typeof jsonProp === 'object') {
296
+ const res: Record<string, unknown> = {};
297
+ let usedVars: Set<Variable> | undefined;
298
+ for (const key in jsonProp) {
299
+ const subres = applyVars(jsonProp[key as keyof typeof jsonProp], opts);
300
+ res[key] = subres.result;
301
+
302
+ if (subres.usedVars) {
303
+ if (!usedVars) {
304
+ usedVars = new Set();
305
+ }
306
+ for (const instance of subres.usedVars) {
307
+ usedVars.add(instance);
308
+ }
309
+ }
310
+ }
311
+ return {
312
+ result: res as MaybeMissing<T>,
313
+ usedVars
314
+ };
315
+ }
316
+ }
317
+ return {
318
+ result: jsonProp
319
+ };
320
+ }
321
+
322
+ export interface PreparedExpression<T> {
323
+ vars: string[];
324
+ hasExpression: boolean;
325
+ applyVars: (
326
+ variables: VariablesMap,
327
+ customFunctions?: CustomFunctions,
328
+ keepComplex?: boolean
329
+ ) => {
330
+ result: MaybeMissing<T>;
331
+ usedVars?: Set<Variable>;
332
+ };
333
+ }
334
+
335
+ export function prepareVars<T>(
336
+ jsonProp: T,
337
+ logError: LogError,
338
+ store: Store | undefined,
339
+ weekStartDay: number,
340
+ maxDepth = Infinity
341
+ ): PreparedExpression<T> {
342
+ const result: {
343
+ vars: string[];
344
+ hasExpression: boolean;
345
+ } = {
346
+ vars: [],
347
+ hasExpression: false
348
+ };
349
+ const root = prepareVarsObj(jsonProp, result, logError, maxDepth);
350
+
351
+ const vars = uniq(result.vars);
352
+
353
+ return {
354
+ vars,
355
+ hasExpression: result.hasExpression,
356
+ applyVars(variables, customFunctions, keepComplex) {
357
+ return applyVars<T>(root as T, {
358
+ variables,
359
+ customFunctions,
360
+ logError,
361
+ store,
362
+ weekStartDay,
363
+ keepComplex
364
+ });
365
+ }
366
+ };
367
+ }
@@ -0,0 +1,32 @@
1
+ import type { Node } from './ast';
2
+
3
+ /**
4
+ * LRU cache
5
+ * JavaScript Map iteration is guaranteed to be performed in the insertation order
6
+ * On usage, remove the item from the Map and insert it in the end
7
+ */
8
+
9
+ const MAX_ENTRIES = 128;
10
+
11
+ const cache = new Map();
12
+ let latestItem: string | undefined;
13
+
14
+ export function cacheGet(expr: string): Node | undefined {
15
+ return cache.get(expr);
16
+ }
17
+
18
+ export function cacheSet(expr: string, ast: Node): void {
19
+ if (expr === latestItem) {
20
+ return;
21
+ }
22
+
23
+ cache.delete(expr);
24
+
25
+ if (cache.size >= MAX_ENTRIES) {
26
+ cache.delete(cache.keys().next().value);
27
+ }
28
+
29
+ cache.set(expr, ast);
30
+
31
+ latestItem = expr;
32
+ }
@@ -0,0 +1,57 @@
1
+ export function simpleUnescapeString(str: string): string {
2
+ let res = '';
3
+ let isAt = false;
4
+ let isBackslash = false;
5
+
6
+ for (let i = 0; i < str.length; ++i) {
7
+ const char = str.charAt(i);
8
+ if (char === '\\') {
9
+ if (isAt) {
10
+ isAt = false;
11
+ res += '@';
12
+ }
13
+ if (isBackslash) {
14
+ res += char;
15
+ isBackslash = false;
16
+ } else {
17
+ isBackslash = true;
18
+ }
19
+ } else if (char === '@') {
20
+ if (isBackslash) {
21
+ res += char;
22
+ } else if (isAt) {
23
+ res += char;
24
+ } else {
25
+ isAt = true;
26
+ }
27
+ } else if (char === '{') {
28
+ if (isAt) {
29
+ throw new Error('Expressions is not supported');
30
+ } else {
31
+ res += char;
32
+ }
33
+ } else {
34
+ if (isBackslash) {
35
+ throw new Error('Incorrect escape');
36
+ }
37
+ if (isAt) {
38
+ isAt = false;
39
+ res += '@';
40
+ }
41
+ res += char;
42
+ }
43
+
44
+ if (isBackslash && char !== '\\') {
45
+ isBackslash = false;
46
+ }
47
+ }
48
+
49
+ if (isAt) {
50
+ res += '@';
51
+ }
52
+ if (isBackslash) {
53
+ throw new Error('Incorrect escape');
54
+ }
55
+
56
+ return res;
57
+ }