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,412 @@
1
+ import { parseColor } from '../../utils/correctColor';
2
+ import { toBigInt } from '../bigint';
3
+ import { ARRAY, BOOLEAN, COLOR, DICT, FUNCTION, INTEGER, NUMBER, STRING, URL } from '../const';
4
+ import { logFunctionMatchError, type ArrayValue, type BooleanValue, type ColorValue, type EvalContext, type EvalTypes, type EvalValue, type FuncValue, type IntegerValue, type NumberValue, type StringValue, type UrlValue } from '../eval';
5
+ import { checkIntegerOverflow, checkUrl, convertJsValueToDivKit, safeCheckUrl, transformColorValue, typeToString } from '../utils';
6
+ import { findBestMatchedFuncList, registerFunc, registerMethod, type Func, type FuncMatch } from './funcs';
7
+
8
+ function arrayGetter(jsType: string, runtimeType: string) {
9
+ return (ctx: EvalContext, array: ArrayValue, index: IntegerValue): EvalValue => {
10
+ if (index.value < 0 || index.value >= array.value.length) {
11
+ throw new Error(`Requested index (${index.value}) out of bounds array size (${array.value.length}).`);
12
+ }
13
+ let val = array.value[Number(index.value)];
14
+
15
+ let type: string = typeof val;
16
+ if (
17
+ jsType === 'array' && !Array.isArray(val) ||
18
+ jsType !== 'array' && type !== jsType ||
19
+ type === 'object' && val === null
20
+ ) {
21
+ if (type === 'object') {
22
+ if (Array.isArray(val)) {
23
+ type = 'Array';
24
+ } else if (val === null) {
25
+ type = 'Null';
26
+ } else {
27
+ type = 'Dict';
28
+ }
29
+ }
30
+ throw new Error(`Incorrect value type: expected ${typeToString(runtimeType)}, got ${typeToString(type)}.`);
31
+ }
32
+ if (jsType === 'number' && runtimeType === 'integer') {
33
+ checkIntegerOverflow(ctx, val as number);
34
+ try {
35
+ val = toBigInt(val as number);
36
+ } catch (_err) {
37
+ throw new Error('Cannot convert value to integer.');
38
+ }
39
+ }
40
+ if (jsType === 'string' && runtimeType === 'color') {
41
+ val = transformColorValue(val as string);
42
+ }
43
+ if (jsType === 'string' && runtimeType === 'url') {
44
+ checkUrl(val);
45
+ }
46
+
47
+ return {
48
+ type: runtimeType,
49
+ value: val
50
+ } as EvalValue;
51
+ };
52
+ }
53
+
54
+ function optWrapper<ValueType extends EvalValue>(
55
+ func: (ctx: EvalContext, array: ArrayValue, index: IntegerValue) => EvalValue,
56
+ fallbackType: EvalTypes
57
+ ) {
58
+ return (ctx: EvalContext, array: ArrayValue, index: IntegerValue, fallback: ValueType) => {
59
+ try {
60
+ return func(ctx, array, index);
61
+ } catch (_err) {
62
+ // ignore error
63
+
64
+ let value = fallback.value;
65
+ if (fallbackType === 'color') {
66
+ value = transformColorValue(value as string);
67
+ } else if (fallbackType === 'url') {
68
+ checkUrl(value);
69
+ }
70
+ return {
71
+ type: fallbackType,
72
+ value
73
+ } as unknown as EvalValue;
74
+ }
75
+ };
76
+ }
77
+
78
+ const getArrayString = arrayGetter('string', 'string');
79
+ const getArrayNumber = arrayGetter('number', 'number');
80
+ const getArrayInteger = arrayGetter('number', 'integer');
81
+ const getArrayBoolean = arrayGetter('boolean', 'boolean');
82
+ const getArrayColor = arrayGetter('string', 'color');
83
+ const getArrayUrl = arrayGetter('string', 'url');
84
+ const getArrayArray = arrayGetter('array', 'array');
85
+ const getArrayDict = arrayGetter('object', 'dict');
86
+
87
+ const getArrayOptString = optWrapper<StringValue>(getArrayString, 'string');
88
+ const getArrayOptNumber = optWrapper<NumberValue>(getArrayNumber, 'number');
89
+ const getArrayOptInteger = optWrapper<IntegerValue>(getArrayInteger, 'integer');
90
+ const getArrayOptBoolean = optWrapper<BooleanValue>(getArrayBoolean, 'boolean');
91
+ const getArrayOptColor = optWrapper<ColorValue>(getArrayColor, 'color');
92
+ const getArrayOptUrl = optWrapper<UrlValue>(getArrayUrl, 'url');
93
+
94
+ function getArrayOptArray(ctx: EvalContext, array: ArrayValue, index: IntegerValue): EvalValue {
95
+ try {
96
+ return getArrayArray(ctx, array, index);
97
+ } catch (_err) {
98
+ // ignore error
99
+ return {
100
+ type: ARRAY,
101
+ value: []
102
+ } as unknown as EvalValue;
103
+ }
104
+ }
105
+
106
+ function getArrayOptDict(ctx: EvalContext, array: ArrayValue, index: IntegerValue): EvalValue {
107
+ try {
108
+ return getArrayDict(ctx, array, index);
109
+ } catch (_err) {
110
+ // ignore error
111
+ return {
112
+ type: DICT,
113
+ value: {}
114
+ } as unknown as EvalValue;
115
+ }
116
+ }
117
+
118
+ function len(_ctx: EvalContext, array: ArrayValue): EvalValue {
119
+ return {
120
+ type: INTEGER,
121
+ value: toBigInt(array.value.length)
122
+ };
123
+ }
124
+
125
+ function isEmpty(_ctx: EvalContext, array: ArrayValue): EvalValue {
126
+ return {
127
+ type: BOOLEAN,
128
+ value: array.value.length === 0 ? 1 : 0
129
+ };
130
+ }
131
+
132
+ function filter(ctx: EvalContext, array: ArrayValue, fn: FuncValue): EvalValue {
133
+ if (!array.value.length) {
134
+ return {
135
+ type: ARRAY,
136
+ value: []
137
+ };
138
+ }
139
+
140
+ return {
141
+ type: ARRAY,
142
+ value: array.value.filter(it => {
143
+ const argMatchers: EvalValue[][] = [];
144
+
145
+ if (typeof it === 'string') {
146
+ if (parseColor(it)) {
147
+ argMatchers.push([{
148
+ type: COLOR,
149
+ value: it
150
+ }]);
151
+ }
152
+ if (safeCheckUrl(it)) {
153
+ argMatchers.push([{
154
+ type: URL,
155
+ value: it
156
+ }]);
157
+ }
158
+ argMatchers.push([{
159
+ type: STRING,
160
+ value: it
161
+ }]);
162
+ } else if (typeof it === 'number') {
163
+ if (Math.round(it) === it) {
164
+ checkIntegerOverflow(ctx, it);
165
+ argMatchers.push([{
166
+ type: INTEGER,
167
+ value: toBigInt(it)
168
+ }]);
169
+ }
170
+ argMatchers.push([{
171
+ type: NUMBER,
172
+ value: it
173
+ }]);
174
+ } else if (typeof it === 'bigint') {
175
+ checkIntegerOverflow(ctx, it);
176
+ argMatchers.push([{
177
+ type: INTEGER,
178
+ value: it
179
+ }]);
180
+ } else if (Array.isArray(it)) {
181
+ argMatchers.push([{
182
+ type: ARRAY,
183
+ value: it
184
+ }]);
185
+ } else if (typeof it === 'object') {
186
+ if (it === null) {
187
+ throw new Error('Incorrect value type: Null');
188
+ }
189
+ argMatchers.push([{
190
+ type: DICT,
191
+ value: it
192
+ }]);
193
+ } else if (typeof it === 'boolean') {
194
+ argMatchers.push([{
195
+ type: BOOLEAN,
196
+ value: it ? 1 : 0
197
+ }]);
198
+ } else {
199
+ throw new Error(`Incorrect value type: ${typeToString(typeof it)}`);
200
+ }
201
+
202
+ let fnMatch: FuncMatch = {
203
+ type: 'missing'
204
+ };
205
+ for (const matchItem of argMatchers) {
206
+ fnMatch = findBestMatchedFuncList(fn.value, matchItem);
207
+ if ('func' in fnMatch) {
208
+ break;
209
+ }
210
+ }
211
+
212
+ let selectedFn: Func;
213
+ if ('func' in fnMatch) {
214
+ selectedFn = fnMatch.func;
215
+ } else {
216
+ const selectedFn = fn.value[0];
217
+ logFunctionMatchError(selectedFn.name || 'Function', argMatchers[0], fnMatch, true);
218
+ }
219
+
220
+ const argType = selectedFn.args[0];
221
+ const value = convertJsValueToDivKit(
222
+ ctx,
223
+ it,
224
+ typeof argType === 'string' ? argType : argType.type
225
+ );
226
+ const res = selectedFn.cb(ctx, value);
227
+
228
+ if (res.type !== BOOLEAN) {
229
+ throw new Error('Function must return boolean value.');
230
+ }
231
+
232
+ return res.value;
233
+ })
234
+ };
235
+ }
236
+
237
+ export function registerArray(): void {
238
+ registerFunc('getArrayString', [
239
+ ARRAY,
240
+ INTEGER
241
+ ], getArrayString);
242
+ registerFunc('getStringFromArray', [
243
+ ARRAY,
244
+ INTEGER
245
+ ], getArrayString);
246
+
247
+ registerFunc('getArrayNumber', [
248
+ ARRAY,
249
+ INTEGER
250
+ ], getArrayNumber);
251
+ registerFunc('getNumberFromArray', [
252
+ ARRAY,
253
+ INTEGER
254
+ ], getArrayNumber);
255
+
256
+ registerFunc('getArrayInteger', [
257
+ ARRAY,
258
+ INTEGER
259
+ ], getArrayInteger);
260
+ registerFunc('getIntegerFromArray', [
261
+ ARRAY,
262
+ INTEGER
263
+ ], getArrayInteger);
264
+
265
+ registerFunc('getArrayBoolean', [
266
+ ARRAY,
267
+ INTEGER
268
+ ], getArrayBoolean);
269
+ registerFunc('getBooleanFromArray', [
270
+ ARRAY,
271
+ INTEGER
272
+ ], getArrayBoolean);
273
+
274
+ registerFunc('getArrayColor', [
275
+ ARRAY,
276
+ INTEGER
277
+ ], getArrayColor);
278
+ registerFunc('getColorFromArray', [
279
+ ARRAY,
280
+ INTEGER
281
+ ], getArrayColor);
282
+
283
+ registerFunc('getArrayUrl', [
284
+ ARRAY,
285
+ INTEGER
286
+ ], getArrayUrl);
287
+ registerFunc('getUrlFromArray', [
288
+ ARRAY,
289
+ INTEGER
290
+ ], getArrayUrl);
291
+
292
+ registerFunc('getArrayFromArray', [
293
+ ARRAY,
294
+ INTEGER
295
+ ], getArrayArray);
296
+
297
+ registerFunc('getDictFromArray', [
298
+ ARRAY,
299
+ INTEGER
300
+ ], getArrayDict);
301
+
302
+ registerFunc('getArrayOptString', [
303
+ ARRAY,
304
+ INTEGER,
305
+ STRING
306
+ ], getArrayOptString);
307
+ registerFunc('getOptStringFromArray', [
308
+ ARRAY,
309
+ INTEGER,
310
+ STRING
311
+ ], getArrayOptString);
312
+
313
+ registerFunc('getArrayOptNumber', [
314
+ ARRAY,
315
+ INTEGER,
316
+ NUMBER
317
+ ], getArrayOptNumber);
318
+ registerFunc('getOptNumberFromArray', [
319
+ ARRAY,
320
+ INTEGER,
321
+ NUMBER
322
+ ], getArrayOptNumber);
323
+
324
+ registerFunc('getArrayOptInteger', [
325
+ ARRAY,
326
+ INTEGER,
327
+ INTEGER
328
+ ], getArrayOptInteger);
329
+ registerFunc('getOptIntegerFromArray', [
330
+ ARRAY,
331
+ INTEGER,
332
+ INTEGER
333
+ ], getArrayOptInteger);
334
+
335
+ registerFunc('getArrayOptBoolean', [
336
+ ARRAY,
337
+ INTEGER,
338
+ BOOLEAN
339
+ ], getArrayOptBoolean);
340
+ registerFunc('getOptBooleanFromArray', [
341
+ ARRAY,
342
+ INTEGER,
343
+ BOOLEAN
344
+ ], getArrayOptBoolean);
345
+
346
+ registerFunc('getArrayOptColor', [
347
+ ARRAY,
348
+ INTEGER,
349
+ COLOR
350
+ ], getArrayOptColor);
351
+ registerFunc('getOptColorFromArray', [
352
+ ARRAY,
353
+ INTEGER,
354
+ COLOR
355
+ ], getArrayOptColor);
356
+ registerFunc('getArrayOptColor', [
357
+ ARRAY,
358
+ INTEGER,
359
+ STRING
360
+ ], getArrayOptColor);
361
+ registerFunc('getOptColorFromArray', [
362
+ ARRAY,
363
+ INTEGER,
364
+ STRING
365
+ ], getArrayOptColor);
366
+
367
+ registerFunc('getArrayOptUrl', [
368
+ ARRAY,
369
+ INTEGER,
370
+ URL
371
+ ], getArrayOptUrl);
372
+ registerFunc('getOptUrlFromArray', [
373
+ ARRAY,
374
+ INTEGER,
375
+ URL
376
+ ], getArrayOptUrl);
377
+ registerFunc('getArrayOptUrl', [
378
+ ARRAY,
379
+ INTEGER,
380
+ STRING
381
+ ], getArrayOptUrl);
382
+ registerFunc('getOptUrlFromArray', [
383
+ ARRAY,
384
+ INTEGER,
385
+ STRING
386
+ ], getArrayOptUrl);
387
+
388
+ registerFunc('getOptArrayFromArray', [
389
+ ARRAY,
390
+ INTEGER
391
+ ], getArrayOptArray);
392
+
393
+ registerFunc('getOptDictFromArray', [
394
+ ARRAY,
395
+ INTEGER
396
+ ], getArrayOptDict);
397
+
398
+ registerFunc('len', [
399
+ ARRAY
400
+ ], len);
401
+
402
+ registerMethod('getString', [ARRAY, INTEGER], getArrayString);
403
+ registerMethod('getInteger', [ARRAY, INTEGER], getArrayInteger);
404
+ registerMethod('getNumber', [ARRAY, INTEGER], getArrayNumber);
405
+ registerMethod('getBoolean', [ARRAY, INTEGER], getArrayBoolean);
406
+ registerMethod('getUrl', [ARRAY, INTEGER], getArrayUrl);
407
+ registerMethod('getColor', [ARRAY, INTEGER], getArrayColor);
408
+ registerMethod('getArray', [ARRAY, INTEGER], getArrayArray);
409
+ registerMethod('getDict', [ARRAY, INTEGER], getArrayDict);
410
+ registerMethod('isEmpty', [ARRAY], isEmpty);
411
+ registerMethod('filter', [ARRAY, FUNCTION], filter);
412
+ }
@@ -0,0 +1,100 @@
1
+ import type { ColorValue, EvalContext, EvalValue, NumberValue, StringValue } from '../eval';
2
+ import type { ParsedColor } from '../../utils/correctColor';
3
+ import { registerFunc } from './funcs';
4
+ import { COLOR, NUMBER, STRING } from '../const';
5
+ import { safeConvertColor, stringifyColor } from '../utils';
6
+
7
+ function colorGetter(
8
+ field: keyof ParsedColor
9
+ ): (_ctx: EvalContext, color: StringValue | ColorValue) => EvalValue {
10
+ return (_vars, color) => {
11
+ const parsed = safeConvertColor(color.value);
12
+
13
+ return {
14
+ type: NUMBER,
15
+ value: parsed[field] / 255
16
+ };
17
+ };
18
+ }
19
+
20
+ function colorSetter(
21
+ field: keyof ParsedColor
22
+ ): (_ctx: EvalContext, color: StringValue | ColorValue, val: NumberValue) => EvalValue {
23
+ return (_vars, color, val) => {
24
+ const parsed = safeConvertColor(color.value);
25
+
26
+ parsed[field] = val.value * 255;
27
+
28
+ return {
29
+ type: COLOR,
30
+ value: stringifyColor(parsed)
31
+ };
32
+ };
33
+ }
34
+
35
+ const getColorAlpha = colorGetter('a');
36
+ const getColorRed = colorGetter('r');
37
+ const getColorGreen = colorGetter('g');
38
+ const getColorBlue = colorGetter('b');
39
+
40
+ const setColorAlpha = colorSetter('a');
41
+ const setColorRed = colorSetter('r');
42
+ const setColorGreen = colorSetter('g');
43
+ const setColorBlue = colorSetter('b');
44
+
45
+ function rgb(_ctx: EvalContext, red: NumberValue, green: NumberValue, blue: NumberValue): EvalValue {
46
+ const parsed: ParsedColor = {
47
+ a: 255,
48
+ r: red.value * 255,
49
+ g: green.value * 255,
50
+ b: blue.value * 255
51
+ };
52
+
53
+ return {
54
+ type: COLOR,
55
+ value: stringifyColor(parsed)
56
+ };
57
+ }
58
+
59
+ function argb(
60
+ _ctx: EvalContext,
61
+ alpha: NumberValue,
62
+ red: NumberValue,
63
+ green: NumberValue,
64
+ blue: NumberValue
65
+ ): EvalValue {
66
+ const parsed: ParsedColor = {
67
+ a: alpha.value * 255,
68
+ r: red.value * 255,
69
+ g: green.value * 255,
70
+ b: blue.value * 255
71
+ };
72
+
73
+ return {
74
+ type: COLOR,
75
+ value: stringifyColor(parsed)
76
+ };
77
+ }
78
+
79
+ export function registerColors(): void {
80
+ registerFunc('getColorAlpha', [STRING], getColorAlpha);
81
+ registerFunc('getColorAlpha', [COLOR], getColorAlpha);
82
+ registerFunc('getColorRed', [STRING], getColorRed);
83
+ registerFunc('getColorRed', [COLOR], getColorRed);
84
+ registerFunc('getColorGreen', [STRING], getColorGreen);
85
+ registerFunc('getColorGreen', [COLOR], getColorGreen);
86
+ registerFunc('getColorBlue', [STRING], getColorBlue);
87
+ registerFunc('getColorBlue', [COLOR], getColorBlue);
88
+
89
+ registerFunc('setColorAlpha', [STRING, NUMBER], setColorAlpha);
90
+ registerFunc('setColorAlpha', [COLOR, NUMBER], setColorAlpha);
91
+ registerFunc('setColorRed', [STRING, NUMBER], setColorRed);
92
+ registerFunc('setColorRed', [COLOR, NUMBER], setColorRed);
93
+ registerFunc('setColorGreen', [STRING, NUMBER], setColorGreen);
94
+ registerFunc('setColorGreen', [COLOR, NUMBER], setColorGreen);
95
+ registerFunc('setColorBlue', [STRING, NUMBER], setColorBlue);
96
+ registerFunc('setColorBlue', [COLOR, NUMBER], setColorBlue);
97
+
98
+ registerFunc('rgb', [NUMBER, NUMBER, NUMBER], rgb);
99
+ registerFunc('argb', [NUMBER, NUMBER, NUMBER, NUMBER], argb);
100
+ }
@@ -0,0 +1,139 @@
1
+ import type { DivFunction } from '../../../typings/common';
2
+ import type { Node } from '../ast';
3
+ import { evalExpression, type EvalTypes, type VariablesMap } from '../eval';
4
+ import { parse } from '../expressions';
5
+ import type { MaybeMissing } from '../json';
6
+ import { cacheGet, cacheSet } from '../parserCache';
7
+ import { createConstVariable, Variable } from '../variable';
8
+ import { funcToKey, type Func } from './funcs';
9
+
10
+ export type CustomFunctions = Map<string, Func[]>;
11
+
12
+ const supportedTypes = new Set<EvalTypes>([
13
+ 'string',
14
+ 'integer',
15
+ 'number',
16
+ 'boolean',
17
+ 'datetime',
18
+ 'color',
19
+ 'url',
20
+ 'dict',
21
+ 'array'
22
+ ]);
23
+
24
+ export function checkCustomFunction(func: MaybeMissing<DivFunction>): void {
25
+ if (!(typeof func.name === 'string' && func.name)) {
26
+ throw new Error('Incorrect function name');
27
+ }
28
+
29
+ if (!(typeof func.body === 'string' && func.body)) {
30
+ throw new Error('Incorrect function body');
31
+ }
32
+
33
+ if (!(func.return_type && supportedTypes.has(func.return_type))) {
34
+ throw new Error('Incorrect function return_type');
35
+ }
36
+
37
+ if (!Array.isArray(func.arguments)) {
38
+ throw new Error('Incorrect function arguments');
39
+ }
40
+
41
+ const argumentsNames = new Set<string>();
42
+ func.arguments.forEach(arg => {
43
+ if (!(typeof arg.name === 'string' && arg.name)) {
44
+ throw new Error('Incorrect argument name');
45
+ }
46
+
47
+ if (!(arg.type && supportedTypes.has(arg.type))) {
48
+ throw new Error('Incorrect argument type');
49
+ }
50
+
51
+ if (argumentsNames.has(arg.name)) {
52
+ throw new Error('Duplicate argument name');
53
+ }
54
+ argumentsNames.add(arg.name);
55
+ });
56
+ }
57
+
58
+ export function customFunctionWrap(fn: DivFunction): Func {
59
+ let ast: Node | undefined;
60
+
61
+ return {
62
+ name: fn.name,
63
+ args: fn.arguments.map(it => {
64
+ return {
65
+ type: it.type
66
+ };
67
+ }),
68
+ cb(ctx, ...args) {
69
+ if (!ast) {
70
+ ast = cacheGet(fn.body) || parse(fn.body, {
71
+ startRule: 'JsonStringContents'
72
+ });
73
+ cacheSet(fn.body, ast!);
74
+ }
75
+
76
+ const vars: VariablesMap = new Map();
77
+ args.forEach((arg, index) => {
78
+ if (arg.type === 'function') {
79
+ throw new Error('Incorrect argument type: function');
80
+ }
81
+ const instance = createConstVariable(fn.arguments[index].name, arg.type, arg.value);
82
+ vars.set(instance.getName(), instance as Variable);
83
+ });
84
+
85
+ const res = evalExpression(vars, ctx.customFunctions, ctx.store, ast!, {
86
+ weekStartDay: ctx.weekStartDay
87
+ });
88
+ res.warnings.forEach(warn => {
89
+ ctx.warnings.push(warn);
90
+ });
91
+ const result = res.result;
92
+
93
+ if (result.type === 'error') {
94
+ throw new Error(result.value);
95
+ }
96
+
97
+ if (result.type !== fn.return_type) {
98
+ throw new Error('Incorrect function return_type');
99
+ }
100
+
101
+ return result;
102
+ },
103
+ };
104
+ }
105
+
106
+ export function mergeCustomFunctions(
107
+ map0: CustomFunctions | undefined,
108
+ map1: CustomFunctions | undefined
109
+ ): CustomFunctions | undefined {
110
+ if (!map0) {
111
+ return map1 || undefined;
112
+ }
113
+ if (!map1) {
114
+ return map0 || undefined;
115
+ }
116
+
117
+ const merged = new Map();
118
+ const defined = new Set<string>();
119
+ for (const [name, funcs] of map1) {
120
+ for (const func of funcs) {
121
+ const key = funcToKey(name, func);
122
+ defined.add(key);
123
+ }
124
+ merged.set(name, funcs);
125
+ }
126
+ for (const [name, funcs] of map0) {
127
+ for (const func of funcs) {
128
+ const key = funcToKey(name, func);
129
+ if (!defined.has(key)) {
130
+ defined.add(key);
131
+ const list = merged.get(name) || [];
132
+ list.push(func);
133
+ merged.set(name, list);
134
+ }
135
+ }
136
+ }
137
+
138
+ return merged;
139
+ }