@datagrok/helm 2.13.7 → 3.0.0

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 (349) hide show
  1. package/CREDITS.md +164 -0
  2. package/dist/489.js +2 -0
  3. package/dist/489.js.map +1 -0
  4. package/dist/package-test.js +1 -1
  5. package/dist/package-test.js.map +1 -1
  6. package/dist/package.js +1 -1
  7. package/dist/package.js.map +1 -1
  8. package/files/samples/helm-showcase.csv +56 -0
  9. package/package.json +6 -10
  10. package/src/helm-helper.ts +61 -413
  11. package/src/package-api.ts +14 -11
  12. package/src/package-test.ts +0 -2
  13. package/src/package-utils.ts +8 -298
  14. package/src/package.g.ts +2 -8
  15. package/src/package.ts +11 -31
  16. package/src/tests/helm-activity-cliffs.ts +2 -2
  17. package/src/tests/helm-input-tests.ts +83 -0
  18. package/src/tests/parse-helm-tests.ts +7 -57
  19. package/src/tests/properties-widget-tests.ts +21 -11
  20. package/src/utils/helm-grid-cell-renderer.ts +141 -151
  21. package/src/utils/index.ts +3 -7
  22. package/src/widgets/helm-input.ts +42 -12
  23. package/src/widgets/properties-widget.ts +18 -11
  24. package/test-console-output-1.log +103 -706
  25. package/test-record-1.mp4 +0 -0
  26. package/webpack.config.js +1 -12
  27. package/dist/455.js +0 -2
  28. package/dist/455.js.map +0 -1
  29. package/dist/package-dojo.js +0 -2
  30. package/dist/package-dojo.js.map +0 -1
  31. package/helm/JSDraw/Pistoia.HELM-uncompressed.js +0 -9694
  32. package/helm/JSDraw/ReadMe.txt +0 -8
  33. package/helm/JSDraw/Scilligence.JSDraw2.Lite-uncompressed.js +0 -31126
  34. package/helm/dojo/package.ts +0 -41
  35. package/helm/dojo/types.ts +0 -12
  36. package/src/helm-web-editor.ts +0 -68
  37. package/src/tests/get-monomer-tests.ts +0 -214
  38. package/src/tests/helm-service-tests.ts +0 -98
  39. package/src/types/dojo.ts +0 -3
  40. package/src/types/index.ts +0 -5
  41. package/src/utils/get-monomer.ts +0 -90
  42. package/src/utils/helm-service.ts +0 -166
  43. package/vendor/dojo-1.10.10/dijit/BackgroundIframe.js +0 -63
  44. package/vendor/dojo-1.10.10/dijit/BackgroundIframe.js.uncompressed.js +0 -116
  45. package/vendor/dojo-1.10.10/dijit/Destroyable.js +0 -35
  46. package/vendor/dojo-1.10.10/dijit/Destroyable.js.uncompressed.js +0 -83
  47. package/vendor/dojo-1.10.10/dijit/Tooltip.js +0 -240
  48. package/vendor/dojo-1.10.10/dijit/Tooltip.js.uncompressed.js +0 -612
  49. package/vendor/dojo-1.10.10/dijit/Viewport.js +0 -44
  50. package/vendor/dojo-1.10.10/dijit/Viewport.js.uncompressed.js +0 -87
  51. package/vendor/dojo-1.10.10/dijit/WidgetSet.js +0 -76
  52. package/vendor/dojo-1.10.10/dijit/WidgetSet.js.uncompressed.js +0 -247
  53. package/vendor/dojo-1.10.10/dijit/_AttachMixin.js +0 -94
  54. package/vendor/dojo-1.10.10/dijit/_AttachMixin.js.uncompressed.js +0 -238
  55. package/vendor/dojo-1.10.10/dijit/_Contained.js +0 -17
  56. package/vendor/dojo-1.10.10/dijit/_Contained.js.uncompressed.js +0 -56
  57. package/vendor/dojo-1.10.10/dijit/_Container.js +0 -47
  58. package/vendor/dojo-1.10.10/dijit/_Container.js.uncompressed.js +0 -108
  59. package/vendor/dojo-1.10.10/dijit/_CssStateMixin.js +0 -198
  60. package/vendor/dojo-1.10.10/dijit/_CssStateMixin.js.uncompressed.js +0 -372
  61. package/vendor/dojo-1.10.10/dijit/_FocusMixin.js +0 -11
  62. package/vendor/dojo-1.10.10/dijit/_FocusMixin.js.uncompressed.js +0 -66
  63. package/vendor/dojo-1.10.10/dijit/_HasDropDown.js +0 -188
  64. package/vendor/dojo-1.10.10/dijit/_HasDropDown.js.uncompressed.js +0 -472
  65. package/vendor/dojo-1.10.10/dijit/_OnDijitClickMixin.js +0 -8
  66. package/vendor/dojo-1.10.10/dijit/_OnDijitClickMixin.js.uncompressed.js +0 -31
  67. package/vendor/dojo-1.10.10/dijit/_TemplatedMixin.js +0 -90
  68. package/vendor/dojo-1.10.10/dijit/_TemplatedMixin.js.uncompressed.js +0 -205
  69. package/vendor/dojo-1.10.10/dijit/_Widget.js +0 -66
  70. package/vendor/dojo-1.10.10/dijit/_Widget.js.uncompressed.js +0 -352
  71. package/vendor/dojo-1.10.10/dijit/_WidgetBase.js +0 -353
  72. package/vendor/dojo-1.10.10/dijit/_WidgetBase.js.uncompressed.js +0 -1200
  73. package/vendor/dojo-1.10.10/dijit/_base/focus.js +0 -68
  74. package/vendor/dojo-1.10.10/dijit/_base/focus.js.uncompressed.js +0 -207
  75. package/vendor/dojo-1.10.10/dijit/_base/manager.js +0 -10
  76. package/vendor/dojo-1.10.10/dijit/_base/manager.js.uncompressed.js +0 -35
  77. package/vendor/dojo-1.10.10/dijit/_base/place.js +0 -52
  78. package/vendor/dojo-1.10.10/dijit/_base/place.js.uncompressed.js +0 -131
  79. package/vendor/dojo-1.10.10/dijit/_base/popup.js +0 -23
  80. package/vendor/dojo-1.10.10/dijit/_base/popup.js.uncompressed.js +0 -58
  81. package/vendor/dojo-1.10.10/dijit/_base/scroll.js +0 -6
  82. package/vendor/dojo-1.10.10/dijit/_base/scroll.js.uncompressed.js +0 -22
  83. package/vendor/dojo-1.10.10/dijit/_base/sniff.js +0 -3
  84. package/vendor/dojo-1.10.10/dijit/_base/sniff.js.uncompressed.js +0 -12
  85. package/vendor/dojo-1.10.10/dijit/_base/typematic.js +0 -3
  86. package/vendor/dojo-1.10.10/dijit/_base/typematic.js.uncompressed.js +0 -10
  87. package/vendor/dojo-1.10.10/dijit/_base/wai.js +0 -32
  88. package/vendor/dojo-1.10.10/dijit/_base/wai.js.uncompressed.js +0 -109
  89. package/vendor/dojo-1.10.10/dijit/_base/window.js +0 -6
  90. package/vendor/dojo-1.10.10/dijit/_base/window.js.uncompressed.js +0 -18
  91. package/vendor/dojo-1.10.10/dijit/_base.js +0 -4
  92. package/vendor/dojo-1.10.10/dijit/_base.js.uncompressed.js +0 -27
  93. package/vendor/dojo-1.10.10/dijit/a11y.js +0 -109
  94. package/vendor/dojo-1.10.10/dijit/a11y.js.uncompressed.js +0 -191
  95. package/vendor/dojo-1.10.10/dijit/a11yclick.js +0 -66
  96. package/vendor/dojo-1.10.10/dijit/a11yclick.js.uncompressed.js +0 -139
  97. package/vendor/dojo-1.10.10/dijit/focus.js +0 -188
  98. package/vendor/dojo-1.10.10/dijit/focus.js.uncompressed.js +0 -371
  99. package/vendor/dojo-1.10.10/dijit/form/Button.js +0 -49
  100. package/vendor/dojo-1.10.10/dijit/form/Button.js.uncompressed.js +0 -130
  101. package/vendor/dojo-1.10.10/dijit/form/ComboBox.js +0 -4
  102. package/vendor/dojo-1.10.10/dijit/form/ComboBox.js.uncompressed.js +0 -27
  103. package/vendor/dojo-1.10.10/dijit/form/ComboButton.js +0 -21
  104. package/vendor/dojo-1.10.10/dijit/form/ComboButton.js.uncompressed.js +0 -86
  105. package/vendor/dojo-1.10.10/dijit/form/DropDownButton.js +0 -38
  106. package/vendor/dojo-1.10.10/dijit/form/DropDownButton.js.uncompressed.js +0 -102
  107. package/vendor/dojo-1.10.10/dijit/form/ToggleButton.js +0 -7
  108. package/vendor/dojo-1.10.10/dijit/form/ToggleButton.js.uncompressed.js +0 -26
  109. package/vendor/dojo-1.10.10/dijit/form/_ButtonMixin.js +0 -50
  110. package/vendor/dojo-1.10.10/dijit/form/_ButtonMixin.js.uncompressed.js +0 -116
  111. package/vendor/dojo-1.10.10/dijit/form/_FormValueMixin.js +0 -26
  112. package/vendor/dojo-1.10.10/dijit/form/_FormValueMixin.js.uncompressed.js +0 -81
  113. package/vendor/dojo-1.10.10/dijit/form/_FormValueWidget.js +0 -24
  114. package/vendor/dojo-1.10.10/dijit/form/_FormValueWidget.js.uncompressed.js +0 -51
  115. package/vendor/dojo-1.10.10/dijit/form/_FormWidget.js +0 -22
  116. package/vendor/dojo-1.10.10/dijit/form/_FormWidget.js.uncompressed.js +0 -67
  117. package/vendor/dojo-1.10.10/dijit/form/_FormWidgetMixin.js +0 -111
  118. package/vendor/dojo-1.10.10/dijit/form/_FormWidgetMixin.js.uncompressed.js +0 -254
  119. package/vendor/dojo-1.10.10/dijit/form/_ToggleButtonMixin.js +0 -32
  120. package/vendor/dojo-1.10.10/dijit/form/_ToggleButtonMixin.js.uncompressed.js +0 -69
  121. package/vendor/dojo-1.10.10/dijit/hccss.js +0 -9
  122. package/vendor/dojo-1.10.10/dijit/hccss.js.uncompressed.js +0 -21
  123. package/vendor/dojo-1.10.10/dijit/layout/AccordionContainer.js +0 -215
  124. package/vendor/dojo-1.10.10/dijit/layout/AccordionContainer.js.uncompressed.js +0 -550
  125. package/vendor/dojo-1.10.10/dijit/layout/AccordionPane.js +0 -7
  126. package/vendor/dojo-1.10.10/dijit/layout/AccordionPane.js.uncompressed.js +0 -25
  127. package/vendor/dojo-1.10.10/dijit/layout/ContentPane.js +0 -235
  128. package/vendor/dojo-1.10.10/dijit/layout/ContentPane.js.uncompressed.js +0 -653
  129. package/vendor/dojo-1.10.10/dijit/layout/StackContainer.js +0 -171
  130. package/vendor/dojo-1.10.10/dijit/layout/StackContainer.js.uncompressed.js +0 -411
  131. package/vendor/dojo-1.10.10/dijit/layout/StackController.js +0 -194
  132. package/vendor/dojo-1.10.10/dijit/layout/StackController.js.uncompressed.js +0 -410
  133. package/vendor/dojo-1.10.10/dijit/layout/_ContentPaneResizeMixin.js +0 -99
  134. package/vendor/dojo-1.10.10/dijit/layout/_ContentPaneResizeMixin.js.uncompressed.js +0 -236
  135. package/vendor/dojo-1.10.10/dijit/layout/_LayoutWidget.js +0 -47
  136. package/vendor/dojo-1.10.10/dijit/layout/_LayoutWidget.js.uncompressed.js +0 -190
  137. package/vendor/dojo-1.10.10/dijit/layout/utils.js +0 -77
  138. package/vendor/dojo-1.10.10/dijit/layout/utils.js.uncompressed.js +0 -151
  139. package/vendor/dojo-1.10.10/dijit/main.js +0 -4
  140. package/vendor/dojo-1.10.10/dijit/main.js.uncompressed.js +0 -16
  141. package/vendor/dojo-1.10.10/dijit/nls/dijit-all_en-us.js +0 -2
  142. package/vendor/dojo-1.10.10/dijit/nls/dijit-all_en-us.js.uncompressed.js +0 -21
  143. package/vendor/dojo-1.10.10/dijit/nls/loading.js +0 -2
  144. package/vendor/dojo-1.10.10/dijit/nls/loading.js.uncompressed.js +0 -47
  145. package/vendor/dojo-1.10.10/dijit/place.js +0 -142
  146. package/vendor/dojo-1.10.10/dijit/place.js.uncompressed.js +0 -407
  147. package/vendor/dojo-1.10.10/dijit/popup.js +0 -162
  148. package/vendor/dojo-1.10.10/dijit/popup.js.uncompressed.js +0 -441
  149. package/vendor/dojo-1.10.10/dijit/registry.js +0 -79
  150. package/vendor/dojo-1.10.10/dijit/registry.js.uncompressed.js +0 -159
  151. package/vendor/dojo-1.10.10/dijit/selection.js +0 -364
  152. package/vendor/dojo-1.10.10/dijit/selection.js.uncompressed.js +0 -525
  153. package/vendor/dojo-1.10.10/dijit/typematic.js +0 -96
  154. package/vendor/dojo-1.10.10/dijit/typematic.js.uncompressed.js +0 -211
  155. package/vendor/dojo-1.10.10/dojo/NodeList-manipulate.js +0 -195
  156. package/vendor/dojo-1.10.10/dojo/NodeList-manipulate.js.uncompressed.js +0 -761
  157. package/vendor/dojo-1.10.10/dojo/Stateful.js +0 -90
  158. package/vendor/dojo-1.10.10/dojo/Stateful.js.uncompressed.js +0 -218
  159. package/vendor/dojo-1.10.10/dojo/_base/url.js +0 -87
  160. package/vendor/dojo-1.10.10/dojo/_base/url.js.uncompressed.js +0 -109
  161. package/vendor/dojo-1.10.10/dojo/cache.js +0 -9
  162. package/vendor/dojo-1.10.10/dojo/cache.js.uncompressed.js +0 -7
  163. package/vendor/dojo-1.10.10/dojo/colors.js +0 -74
  164. package/vendor/dojo-1.10.10/dojo/colors.js.uncompressed.js +0 -232
  165. package/vendor/dojo-1.10.10/dojo/cookie.js +0 -48
  166. package/vendor/dojo-1.10.10/dojo/cookie.js.uncompressed.js +0 -98
  167. package/vendor/dojo-1.10.10/dojo/date/stamp.js +0 -82
  168. package/vendor/dojo-1.10.10/dojo/date/stamp.js.uncompressed.js +0 -144
  169. package/vendor/dojo-1.10.10/dojo/dojo.js +0 -7
  170. package/vendor/dojo-1.10.10/dojo/dojo.js.uncompressed.js +0 -18680
  171. package/vendor/dojo-1.10.10/dojo/fx/Toggler.js +0 -27
  172. package/vendor/dojo-1.10.10/dojo/fx/Toggler.js.uncompressed.js +0 -101
  173. package/vendor/dojo-1.10.10/dojo/fx/easing.js +0 -165
  174. package/vendor/dojo-1.10.10/dojo/fx/easing.js.uncompressed.js +0 -276
  175. package/vendor/dojo-1.10.10/dojo/fx.js +0 -271
  176. package/vendor/dojo-1.10.10/dojo/fx.js.uncompressed.js +0 -443
  177. package/vendor/dojo-1.10.10/dojo/hccss.js +0 -26
  178. package/vendor/dojo-1.10.10/dojo/hccss.js.uncompressed.js +0 -52
  179. package/vendor/dojo-1.10.10/dojo/html.js +0 -161
  180. package/vendor/dojo-1.10.10/dojo/html.js.uncompressed.js +0 -370
  181. package/vendor/dojo-1.10.10/dojo/io/iframe.js +0 -71
  182. package/vendor/dojo-1.10.10/dojo/io/iframe.js.uncompressed.js +0 -190
  183. package/vendor/dojo-1.10.10/dojo/io/script.js +0 -112
  184. package/vendor/dojo-1.10.10/dojo/io/script.js.uncompressed.js +0 -280
  185. package/vendor/dojo-1.10.10/dojo/parser.js +0 -437
  186. package/vendor/dojo-1.10.10/dojo/parser.js.uncompressed.js +0 -915
  187. package/vendor/dojo-1.10.10/dojo/promise/all.js +0 -59
  188. package/vendor/dojo-1.10.10/dojo/promise/all.js.uncompressed.js +0 -77
  189. package/vendor/dojo-1.10.10/dojo/regexp.js +0 -32
  190. package/vendor/dojo-1.10.10/dojo/regexp.js.uncompressed.js +0 -70
  191. package/vendor/dojo-1.10.10/dojo/request/iframe.js +0 -291
  192. package/vendor/dojo-1.10.10/dojo/request/iframe.js.uncompressed.js +0 -438
  193. package/vendor/dojo-1.10.10/dojo/request/script.js +0 -129
  194. package/vendor/dojo-1.10.10/dojo/request/script.js.uncompressed.js +0 -237
  195. package/vendor/dojo-1.10.10/dojo/require.js +0 -11
  196. package/vendor/dojo-1.10.10/dojo/require.js.uncompressed.js +0 -7
  197. package/vendor/dojo-1.10.10/dojo/resources/blank.gif +0 -0
  198. package/vendor/dojo-1.10.10/dojo/string.js +0 -67
  199. package/vendor/dojo-1.10.10/dojo/string.js.uncompressed.js +0 -181
  200. package/vendor/dojo-1.10.10/dojo/touch.js +0 -191
  201. package/vendor/dojo-1.10.10/dojo/touch.js.uncompressed.js +0 -468
  202. package/vendor/dojo-1.10.10/dojo/uacss.js +0 -36
  203. package/vendor/dojo-1.10.10/dojo/uacss.js.uncompressed.js +0 -85
  204. package/vendor/dojo-1.10.10/dojo/window.js +0 -141
  205. package/vendor/dojo-1.10.10/dojo/window.js.uncompressed.js +0 -241
  206. package/vendor/dojo-1.10.10/dojox/charting/Chart.js +0 -626
  207. package/vendor/dojo-1.10.10/dojox/charting/Chart.js.uncompressed.js +0 -1220
  208. package/vendor/dojo-1.10.10/dojox/charting/Chart2D.js +0 -5
  209. package/vendor/dojo-1.10.10/dojox/charting/Chart2D.js.uncompressed.js +0 -16
  210. package/vendor/dojo-1.10.10/dojox/charting/Element.js +0 -247
  211. package/vendor/dojo-1.10.10/dojox/charting/Element.js.uncompressed.js +0 -402
  212. package/vendor/dojo-1.10.10/dojox/charting/Series.js +0 -24
  213. package/vendor/dojo-1.10.10/dojox/charting/Series.js.uncompressed.js +0 -58
  214. package/vendor/dojo-1.10.10/dojox/charting/SimpleTheme.js +0 -191
  215. package/vendor/dojo-1.10.10/dojox/charting/SimpleTheme.js.uncompressed.js +0 -577
  216. package/vendor/dojo-1.10.10/dojox/charting/Theme.js +0 -42
  217. package/vendor/dojo-1.10.10/dojox/charting/Theme.js.uncompressed.js +0 -120
  218. package/vendor/dojo-1.10.10/dojox/charting/action2d/Base.js +0 -11
  219. package/vendor/dojo-1.10.10/dojox/charting/action2d/Base.js.uncompressed.js +0 -36
  220. package/vendor/dojo-1.10.10/dojox/charting/action2d/Highlight.js +0 -77
  221. package/vendor/dojo-1.10.10/dojox/charting/action2d/Highlight.js.uncompressed.js +0 -144
  222. package/vendor/dojo-1.10.10/dojox/charting/action2d/Magnify.js +0 -58
  223. package/vendor/dojo-1.10.10/dojox/charting/action2d/Magnify.js.uncompressed.js +0 -123
  224. package/vendor/dojo-1.10.10/dojox/charting/action2d/MoveSlice.js +0 -54
  225. package/vendor/dojo-1.10.10/dojox/charting/action2d/MoveSlice.js.uncompressed.js +0 -124
  226. package/vendor/dojo-1.10.10/dojox/charting/action2d/PlotAction.js +0 -28
  227. package/vendor/dojo-1.10.10/dojox/charting/action2d/PlotAction.js.uncompressed.js +0 -74
  228. package/vendor/dojo-1.10.10/dojox/charting/action2d/Tooltip.js +0 -116
  229. package/vendor/dojo-1.10.10/dojox/charting/action2d/Tooltip.js.uncompressed.js +0 -178
  230. package/vendor/dojo-1.10.10/dojox/charting/axis2d/Base.js +0 -24
  231. package/vendor/dojo-1.10.10/dojox/charting/axis2d/Base.js.uncompressed.js +0 -83
  232. package/vendor/dojo-1.10.10/dojox/charting/axis2d/Default.js +0 -557
  233. package/vendor/dojo-1.10.10/dojox/charting/axis2d/Default.js.uncompressed.js +0 -980
  234. package/vendor/dojo-1.10.10/dojox/charting/axis2d/Invisible.js +0 -65
  235. package/vendor/dojo-1.10.10/dojox/charting/axis2d/Invisible.js.uncompressed.js +0 -224
  236. package/vendor/dojo-1.10.10/dojox/charting/axis2d/common.js +0 -91
  237. package/vendor/dojo-1.10.10/dojox/charting/axis2d/common.js.uncompressed.js +0 -164
  238. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Areas.js +0 -7
  239. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Areas.js.uncompressed.js +0 -14
  240. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Bars.js +0 -168
  241. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Bars.js.uncompressed.js +0 -311
  242. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Base.js +0 -61
  243. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Base.js.uncompressed.js +0 -161
  244. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Bubble.js +0 -141
  245. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Bubble.js.uncompressed.js +0 -242
  246. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Candlesticks.js +0 -126
  247. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Candlesticks.js.uncompressed.js +0 -243
  248. package/vendor/dojo-1.10.10/dojox/charting/plot2d/CartesianBase.js +0 -108
  249. package/vendor/dojo-1.10.10/dojox/charting/plot2d/CartesianBase.js.uncompressed.js +0 -290
  250. package/vendor/dojo-1.10.10/dojox/charting/plot2d/ClusteredBars.js +0 -13
  251. package/vendor/dojo-1.10.10/dojox/charting/plot2d/ClusteredBars.js.uncompressed.js +0 -14
  252. package/vendor/dojo-1.10.10/dojox/charting/plot2d/ClusteredColumns.js +0 -13
  253. package/vendor/dojo-1.10.10/dojox/charting/plot2d/ClusteredColumns.js.uncompressed.js +0 -14
  254. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Columns.js +0 -153
  255. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Columns.js.uncompressed.js +0 -249
  256. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Default.js +0 -253
  257. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Default.js.uncompressed.js +0 -472
  258. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Grid.js +0 -182
  259. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Grid.js.uncompressed.js +0 -356
  260. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Lines.js +0 -6
  261. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Lines.js.uncompressed.js +0 -12
  262. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Markers.js +0 -6
  263. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Markers.js.uncompressed.js +0 -12
  264. package/vendor/dojo-1.10.10/dojox/charting/plot2d/MarkersOnly.js +0 -7
  265. package/vendor/dojo-1.10.10/dojox/charting/plot2d/MarkersOnly.js.uncompressed.js +0 -13
  266. package/vendor/dojo-1.10.10/dojox/charting/plot2d/OHLC.js +0 -110
  267. package/vendor/dojo-1.10.10/dojox/charting/plot2d/OHLC.js.uncompressed.js +0 -208
  268. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Pie.js +0 -303
  269. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Pie.js.uncompressed.js +0 -547
  270. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Scatter.js +0 -134
  271. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Scatter.js.uncompressed.js +0 -207
  272. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Spider.js +0 -299
  273. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Spider.js.uncompressed.js +0 -537
  274. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Stacked.js +0 -24
  275. package/vendor/dojo-1.10.10/dojox/charting/plot2d/Stacked.js.uncompressed.js +0 -44
  276. package/vendor/dojo-1.10.10/dojox/charting/plot2d/StackedAreas.js +0 -7
  277. package/vendor/dojo-1.10.10/dojox/charting/plot2d/StackedAreas.js.uncompressed.js +0 -14
  278. package/vendor/dojo-1.10.10/dojox/charting/plot2d/StackedBars.js +0 -22
  279. package/vendor/dojo-1.10.10/dojox/charting/plot2d/StackedBars.js.uncompressed.js +0 -33
  280. package/vendor/dojo-1.10.10/dojox/charting/plot2d/StackedColumns.js +0 -20
  281. package/vendor/dojo-1.10.10/dojox/charting/plot2d/StackedColumns.js.uncompressed.js +0 -31
  282. package/vendor/dojo-1.10.10/dojox/charting/plot2d/StackedLines.js +0 -6
  283. package/vendor/dojo-1.10.10/dojox/charting/plot2d/StackedLines.js.uncompressed.js +0 -12
  284. package/vendor/dojo-1.10.10/dojox/charting/plot2d/_PlotEvents.js +0 -68
  285. package/vendor/dojo-1.10.10/dojox/charting/plot2d/_PlotEvents.js.uncompressed.js +0 -120
  286. package/vendor/dojo-1.10.10/dojox/charting/plot2d/common.js +0 -209
  287. package/vendor/dojo-1.10.10/dojox/charting/plot2d/common.js.uncompressed.js +0 -214
  288. package/vendor/dojo-1.10.10/dojox/charting/plot2d/commonStacked.js +0 -76
  289. package/vendor/dojo-1.10.10/dojox/charting/plot2d/commonStacked.js.uncompressed.js +0 -77
  290. package/vendor/dojo-1.10.10/dojox/charting/scaler/common.js +0 -59
  291. package/vendor/dojo-1.10.10/dojox/charting/scaler/common.js.uncompressed.js +0 -70
  292. package/vendor/dojo-1.10.10/dojox/charting/scaler/linear.js +0 -220
  293. package/vendor/dojo-1.10.10/dojox/charting/scaler/linear.js.uncompressed.js +0 -262
  294. package/vendor/dojo-1.10.10/dojox/charting/scaler/primitive.js +0 -23
  295. package/vendor/dojo-1.10.10/dojox/charting/scaler/primitive.js.uncompressed.js +0 -36
  296. package/vendor/dojo-1.10.10/dojox/charting/themes/Claro.js +0 -39
  297. package/vendor/dojo-1.10.10/dojox/charting/themes/Claro.js.uncompressed.js +0 -106
  298. package/vendor/dojo-1.10.10/dojox/charting/themes/Wetland.js +0 -5
  299. package/vendor/dojo-1.10.10/dojox/charting/themes/Wetland.js.uncompressed.js +0 -12
  300. package/vendor/dojo-1.10.10/dojox/charting/themes/common.js +0 -4
  301. package/vendor/dojo-1.10.10/dojox/charting/themes/common.js.uncompressed.js +0 -3
  302. package/vendor/dojo-1.10.10/dojox/charting/widget/Legend.js +0 -102
  303. package/vendor/dojo-1.10.10/dojox/charting/widget/Legend.js.uncompressed.js +0 -165
  304. package/vendor/dojo-1.10.10/dojox/color/Palette.js +0 -163
  305. package/vendor/dojo-1.10.10/dojox/color/Palette.js.uncompressed.js +0 -460
  306. package/vendor/dojo-1.10.10/dojox/color/_base.js +0 -174
  307. package/vendor/dojo-1.10.10/dojox/color/_base.js.uncompressed.js +0 -196
  308. package/vendor/dojo-1.10.10/dojox/gfx/_base.js +0 -253
  309. package/vendor/dojo-1.10.10/dojox/gfx/_base.js.uncompressed.js +0 -1024
  310. package/vendor/dojo-1.10.10/dojox/gfx/fx.js +0 -297
  311. package/vendor/dojo-1.10.10/dojox/gfx/fx.js.uncompressed.js +0 -350
  312. package/vendor/dojo-1.10.10/dojox/gfx/gradutils.js +0 -63
  313. package/vendor/dojo-1.10.10/dojox/gfx/gradutils.js.uncompressed.js +0 -91
  314. package/vendor/dojo-1.10.10/dojox/gfx/matrix.js +0 -170
  315. package/vendor/dojo-1.10.10/dojox/gfx/matrix.js.uncompressed.js +0 -501
  316. package/vendor/dojo-1.10.10/dojox/gfx/path.js +0 -319
  317. package/vendor/dojo-1.10.10/dojox/gfx/path.js.uncompressed.js +0 -478
  318. package/vendor/dojo-1.10.10/dojox/gfx/shape.js +0 -459
  319. package/vendor/dojo-1.10.10/dojox/gfx/shape.js.uncompressed.js +0 -1091
  320. package/vendor/dojo-1.10.10/dojox/gfx/svg.js +0 -662
  321. package/vendor/dojo-1.10.10/dojox/gfx/svg.js.uncompressed.js +0 -1023
  322. package/vendor/dojo-1.10.10/dojox/gfx/utils.js +0 -199
  323. package/vendor/dojo-1.10.10/dojox/gfx/utils.js.uncompressed.js +0 -322
  324. package/vendor/dojo-1.10.10/dojox/gfx.js +0 -2
  325. package/vendor/dojo-1.10.10/dojox/gfx.js.uncompressed.js +0 -1136
  326. package/vendor/dojo-1.10.10/dojox/lang/functional/array.js +0 -151
  327. package/vendor/dojo-1.10.10/dojox/lang/functional/array.js.uncompressed.js +0 -169
  328. package/vendor/dojo-1.10.10/dojox/lang/functional/fold.js +0 -93
  329. package/vendor/dojo-1.10.10/dojox/lang/functional/fold.js.uncompressed.js +0 -125
  330. package/vendor/dojo-1.10.10/dojox/lang/functional/lambda.js +0 -81
  331. package/vendor/dojo-1.10.10/dojox/lang/functional/lambda.js.uncompressed.js +0 -132
  332. package/vendor/dojo-1.10.10/dojox/lang/functional/object.js +0 -54
  333. package/vendor/dojo-1.10.10/dojox/lang/functional/object.js.uncompressed.js +0 -78
  334. package/vendor/dojo-1.10.10/dojox/lang/functional/reversed.js +0 -61
  335. package/vendor/dojo-1.10.10/dojox/lang/functional/reversed.js.uncompressed.js +0 -77
  336. package/vendor/dojo-1.10.10/dojox/lang/functional/scan.js +0 -87
  337. package/vendor/dojo-1.10.10/dojox/lang/functional/scan.js.uncompressed.js +0 -107
  338. package/vendor/dojo-1.10.10/dojox/lang/functional.js +0 -4
  339. package/vendor/dojo-1.10.10/dojox/lang/functional.js.uncompressed.js +0 -3
  340. package/vendor/dojo-1.10.10/dojox/lang/utils.js +0 -86
  341. package/vendor/dojo-1.10.10/dojox/lang/utils.js.uncompressed.js +0 -121
  342. package/vendor/dojo-1.10.10/dojox/main.js +0 -4
  343. package/vendor/dojo-1.10.10/dojox/main.js.uncompressed.js +0 -14
  344. package/vendor/dojo-1.10.10/dojox/storage/LocalStorageProvider.js +0 -112
  345. package/vendor/dojo-1.10.10/dojox/storage/LocalStorageProvider.js.uncompressed.js +0 -208
  346. package/vendor/dojo-1.10.10/dojox/storage/Provider.js +0 -62
  347. package/vendor/dojo-1.10.10/dojox/storage/Provider.js.uncompressed.js +0 -344
  348. package/vendor/dojo-1.10.10/dojox/storage/manager.js +0 -110
  349. package/vendor/dojo-1.10.10/dojox/storage/manager.js.uncompressed.js +0 -263
@@ -4,22 +4,22 @@ import * as DG from 'datagrok-api/dg';
4
4
 
5
5
 
6
6
  import {after, before, category, delay, expect, test, expectArray, timeout} from '@datagrok-libraries/test/src/test';
7
- import {HelmMol, HelmType, IHelmBio, IHelmEditorOptions, Mol, OrgType} from '@datagrok-libraries/bio/src/helm/types';
8
7
  import {getMonomerLibHelper, IMonomerLibHelper} from '@datagrok-libraries/bio/src/types/monomer-library';
9
8
  import {UserLibSettings} from '@datagrok-libraries/bio/src/monomer-works/types';
10
9
  import {
11
10
  getUserLibSettings, setUserLibSettings
12
11
  } from '@datagrok-libraries/bio/src/monomer-works/lib-settings';
13
12
  import {IHelmHelper, getHelmHelper} from '@datagrok-libraries/bio/src/helm/helm-helper';
13
+ import {HelmAtom} from '@datagrok-libraries/bio/src/helm/types';
14
14
 
15
- import {JSDraw2Module} from '../types';
16
15
  import {initHelmMainPackage} from './utils';
17
16
 
18
- declare const org: OrgType;
19
- declare const JSDraw2: JSDraw2Module;
20
-
21
17
  type TestTgtType = { atomCount: number, bondCount: number, helm: string };
22
18
 
19
+ // hwe migration (Phase 7): `helmHelper.parse` now delegates to the standalone
20
+ // `@datagrok-libraries/hwe` parser (immutable `Mol`, exposed as a legacy
21
+ // `HelmMol`-shaped view). The legacy variants that drove `org.helm.webeditor.IO`
22
+ // / `new JSDraw2.Editor(...)` directly were removed with the forked editor.
23
23
  category('parseHelm', () => {
24
24
  const testData: { [testName: string]: { src: string, tgt: TestTgtType } } = {
25
25
  'PT': {
@@ -81,68 +81,18 @@ category('parseHelm', () => {
81
81
  await libHelper.loadMonomerLib(true);
82
82
  });
83
83
 
84
- for (const [testName, {src, tgt}] of Object.entries(testData)) {
85
- test(`Editor-${testName}`, async () => {
86
- _testParseHelmWithEditor(src, tgt);
87
- });
88
- }
89
-
90
84
  for (const [testName, {src, tgt}] of Object.entries(testData)) {
91
85
  test(`HelmHelper-${testName}`, async () => {
92
86
  _testParseHelmWithHelmHelper(src, tgt, helmHelper);
93
87
  });
94
88
  }
95
-
96
- for (const [testName, {src, tgt}] of Object.entries(testData)) {
97
- test(`woDOM-${testName}`, async () => {
98
- _testParseHelmWithoutDOM(src, tgt);
99
- });
100
- }
101
89
  });
102
90
 
103
- function _testParseHelmWithEditor(src: string, tgt: TestTgtType): void {
104
- const io = org.helm.webeditor.IO;
105
-
106
- const editorHost = ui.div();
107
- const editor = new JSDraw2.Editor<HelmType, IHelmBio, IHelmEditorOptions>(editorHost, {viewonly: true});
108
-
109
- const plugin = new org.helm.webeditor.Plugin(editor);
110
- const origin = new JSDraw2.Point(0, 0);
111
- io.parseHelm(plugin, src, origin, undefined);
112
-
113
- const m: HelmMol = plugin.jsd.m;
114
- expect(m.atoms.length, tgt.atomCount);
115
- expect(m.bonds.length, tgt.bondCount);
116
- }
117
-
118
91
  function _testParseHelmWithHelmHelper(src: string, tgt: TestTgtType, helmHelper: IHelmHelper): void {
119
- const io = org.helm.webeditor.IO;
92
+ const resMol = helmHelper.parse(src);
120
93
 
121
- const origin = new JSDraw2.Point(0, 0);
122
- const resMol = helmHelper.parse(src, origin);
123
-
124
- const resHelm = io.getHelm(resMol);
125
94
  expect(resMol.atoms.length, tgt.atomCount);
126
95
  expect(resMol.bonds.length, tgt.bondCount);
127
- expect(resHelm, tgt.helm);
128
- expect(resMol.atoms.every((a) => !a.elem.startsWith('[') && !a.elem.endsWith(']')), true,
129
- 'Atoms should not contain square braces.');
130
- }
131
-
132
- function _testParseHelmWithoutDOM(src: string, tgt: TestTgtType): void {
133
- const io = org.helm.webeditor.IO;
134
-
135
- const molHandler = new JSDraw2.MolHandler<HelmType, IHelmBio, IHelmEditorOptions>();
136
-
137
- const plugin = new org.helm.webeditor.Plugin(molHandler);
138
- const origin = new JSDraw2.Point(0, 0);
139
- io.parseHelm(plugin, src, origin, undefined);
140
-
141
- const m: HelmMol = plugin.jsd.m;
142
- const resHelm = io.getHelm(m);
143
- expect(m.atoms.length, tgt.atomCount);
144
- expect(m.bonds.length, tgt.bondCount);
145
- expect(resHelm, tgt.helm);
146
- expect(m.atoms.every((a) => !a.elem.startsWith('[') && !a.elem.endsWith(']')), true,
96
+ expect(resMol.atoms.every((a: HelmAtom) => !a.elem.startsWith('[') && !a.elem.endsWith(']')), true,
147
97
  'Atoms should not contain square braces.');
148
98
  }
@@ -31,43 +31,53 @@ const enum Tests {
31
31
  fastaDna = 'fasta-DNA',
32
32
  }
33
33
 
34
+ // hwe migration (Phase 7): molecular-weight goldens updated to the standalone
35
+ // `@datagrok-libraries/hwe` calculator, which uses IUPAC-2013 standard atomic
36
+ // weights (C 12.011, O 15.999, S 32.06, P 30.974) instead of the legacy
37
+ // JSDraw2 PT.Lite table (C 12.0107, O 15.9994, S 32.065, P 30.9738). Formulas
38
+ // (legacy C,H,N,O,S,P order) and extinction coefficients are unchanged; only
39
+ // MW shifts by ≤0.04 Da. Source: hwe src/calc/formula.ts.
34
40
  const TestsData: {
35
41
  [testName: string]: { seq: string, units: NOTATION, separator?: string, alphabet?: ALPHABET, res: {} }
36
42
  } = {
37
43
  [Tests.helm]: {
38
44
  seq: 'PEPTIDE1{I.H.A.C.T.[Thr_PO3H2].[Aca].[D-Tyr_Et]}|PEPTIDE2{E.A.[meG]}$PEPTIDE1,PEPTIDE2,4:R3-1:R1$$$V2.0',
39
45
  units: NOTATION.HELM,
40
- res: {[MolProps.formula]: 'C58H94N13O21SP', [MolProps.mw]: 1372.48, [MolProps.extinctCoef]: 1.55}
46
+ res: {[MolProps.formula]: 'C58H94N13O21SP', [MolProps.mw]: 1372.49, [MolProps.extinctCoef]: 1.55}
41
47
  },
42
48
  [Tests.separator]: {
43
49
  seq: 'I/H/A/C/T/Thr_PO3H2/Aca/D-Tyr_Et',
44
50
  units: NOTATION.SEPARATOR, separator: '/', alphabet: ALPHABET.UN,
45
- res: {[MolProps.formula]: 'C47H77N10O15SP', [MolProps.mw]: 1085.21, [MolProps.extinctCoef]: 1.55}
51
+ res: {[MolProps.formula]: 'C47H77N10O15SP', [MolProps.mw]: 1085.22, [MolProps.extinctCoef]: 1.55}
46
52
  },
47
53
  [Tests.separator2]: {
48
54
  seq: 'meI/hHis/Aca/N/T/dK/Thr_PO3H2/Aca/D-Tyr_Et/Aze/dV/E/N////Phe_4Me',
49
55
  units: NOTATION.SEPARATOR, separator: '/', alphabet: ALPHABET.UN,
50
- res: {[MolProps.formula]: 'C91H146N19O25P', [MolProps.mw]: 1937.21, [MolProps.extinctCoef]: 1.49},
56
+ res: {[MolProps.formula]: 'C91H146N19O25P', [MolProps.mw]: 1937.25, [MolProps.extinctCoef]: 1.49},
51
57
  },
52
58
  [Tests.separatorGaps]: {
53
59
  seq: 'I/H/A//T/Thr_PO3H2/Aca/D-Tyr_Et',
54
60
  units: NOTATION.SEPARATOR, separator: '/', alphabet: ALPHABET.UN,
55
- res: {[MolProps.formula]: 'C44H72N9O14P', [MolProps.mw]: 982.07, [MolProps.extinctCoef]: 1.49},
61
+ res: {[MolProps.formula]: 'C44H72N9O14P', [MolProps.mw]: 982.08, [MolProps.extinctCoef]: 1.49},
56
62
  },
57
63
  [Tests.fastaPt]: {
58
64
  seq: 'IHACTTAY',
59
65
  units: NOTATION.FASTA, alphabet: ALPHABET.PT,
60
- res: {[MolProps.formula]: 'C38H58N10O12S', [MolProps.mw]: 878.99, [MolProps.extinctCoef]: 1.55}
66
+ res: {[MolProps.formula]: 'C38H58N10O12S', [MolProps.mw]: 879, [MolProps.extinctCoef]: 1.55}
61
67
  },
62
68
  [Tests.fastaRna]: {
63
69
  seq: 'ACGUAUUCC',
64
70
  units: NOTATION.FASTA, alphabet: ALPHABET.RNA,
65
- res: {[MolProps.formula]: 'C84H107N30O65P9', [MolProps.mw]: 2855.67, [MolProps.extinctCoef]: 96.27}
71
+ // hwe migration: EC now uses hwe's nearest-neighbor stacking model
72
+ // (ε = 2·ΣNN − Σinternal-singletons) instead of the legacy Pistoia
73
+ // sum-of-single-base ε (which gave 96.27). T is scored as U.
74
+ res: {[MolProps.formula]: 'C84H107N30O65P9', [MolProps.mw]: 2855.69, [MolProps.extinctCoef]: 86.96}
66
75
  },
67
76
  [Tests.fastaDna]: {
68
77
  seq: 'ACGTATTCC',
69
78
  units: NOTATION.FASTA, alphabet: ALPHABET.DNA,
70
- res: {[MolProps.formula]: 'C87H113N30O56P9', [MolProps.mw]: 2753.76, [MolProps.extinctCoef]: 91.74}
79
+ // hwe NN model with T≈U (was 91.74 under the legacy sum-of-singles model).
80
+ res: {[MolProps.formula]: 'C87H113N30O56P9', [MolProps.mw]: 2753.78, [MolProps.extinctCoef]: 86.96}
71
81
  }
72
82
  };
73
83
 
@@ -94,7 +104,7 @@ category('properties-widget', () => {
94
104
 
95
105
  for (const [testName, testData] of Object.entries(TestsData)) {
96
106
  test(testName, async () => {
97
- testPropertiesDict(testData.seq, testData.units, testData.separator, testData.alphabet, testData.res);
107
+ await testPropertiesDict(testData.seq, testData.units, testData.separator, testData.alphabet, testData.res);
98
108
  });
99
109
  }
100
110
 
@@ -106,7 +116,7 @@ category('properties-widget', () => {
106
116
  const sh = seqHelper.getSeqHandler(col);
107
117
  let errCatched = true;
108
118
  try {
109
- const _actPropDict = getPropertiesDict(col.get(0), sh);
119
+ const _actPropDict = await getPropertiesDict(col.get(0), sh);
110
120
  const k = 11;
111
121
  } catch (err: any) {
112
122
  if (err instanceof SeqPropertiesError) errCatched = true;
@@ -114,7 +124,7 @@ category('properties-widget', () => {
114
124
  expect(errCatched, true);
115
125
  });
116
126
 
117
- function testPropertiesDict(
127
+ async function testPropertiesDict(
118
128
  seq: string, units: NOTATION, separator: string | undefined, alphabet: ALPHABET | undefined, expPropDict: {}
119
129
  ) {
120
130
  const col = DG.Column.fromStrings('seq', [seq]) as DG.Column<string>;
@@ -123,7 +133,7 @@ category('properties-widget', () => {
123
133
  if (separator) col.setTag(bioTAGS.separator, separator);
124
134
  if (alphabet) col.setTag(bioTAGS.alphabet, alphabet);
125
135
  const sh = seqHelper.getSeqHandler(col);
126
- const actPropDict = getPropertiesDict(seq, sh);
136
+ const actPropDict = await getPropertiesDict(seq, sh);
127
137
  expectObject(actPropDict, expPropDict);
128
138
  }
129
139
  });
@@ -2,16 +2,9 @@ import * as grok from 'datagrok-api/grok';
2
2
  import * as DG from 'datagrok-api/dg';
3
3
  import * as ui from 'datagrok-api/ui';
4
4
 
5
- import wu from 'wu';
6
-
7
- import {HelmType, IHelmBio, ISeqMonomer, Mol} from '@datagrok-libraries/bio/src/helm/types';
8
- import {
9
- CellRendererBackAsyncBase, RenderServiceBase
10
- } from '@datagrok-libraries/bio/src/utils/cell-renderer-async-base';
11
- import {HelmAux, HelmProps, HelmServiceBase} from '@datagrok-libraries/bio/src/viewers/helm-service';
5
+ import {HelmType, IHelmBio, ISeqMonomer, HelmMol, Mol} from '@datagrok-libraries/bio/src/helm/types';
12
6
  import {errInfo} from '@datagrok-libraries/bio/src/utils/err-info';
13
- import {ILogger} from '@datagrok-libraries/bio/src/utils/logger';
14
- import {getGridCellColTemp} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
7
+ import {CellRendererBackBase, getGridCellColTemp} from '@datagrok-libraries/bio/src/utils/cell-renderer-back-base';
15
8
  import {getMonomerLibHelper} from '@datagrok-libraries/bio/src/types/monomer-library';
16
9
  import {IMonomerLibBase} from '@datagrok-libraries/bio/src/types/monomer-library';
17
10
  import {execMonomerHoverLinks} from '@datagrok-libraries/bio/src/monomer-works/monomer-hover';
@@ -23,25 +16,48 @@ import {
23
16
  MacromoleculeHighlightEntry, MacromoleculeHighlightEventArgs, macromoleculeHighlightColorToCss,
24
17
  } from '@datagrok-libraries/bio/src/utils/macromolecule-highlight';
25
18
 
26
- import {getHoveredMonomerFromEditorMol, getSeqMonomerFromHelmAtom} from './get-hovered';
19
+ // Phase 4 (hwe migration): the cell renderer paints synchronously straight into
20
+ // the grid canvas via the standalone `@datagrok-libraries/hwe` library — no
21
+ // async SVG→image / ImageData round-trip. `renderToCanvas` fits + centers +
22
+ // clips the molecule into the cell bounds and returns the laid-out mol plus the
23
+ // model/draw boxes used for hover + highlight overlays.
24
+ import {HelmService as HweHelmService, bridgeMonomerLib, buildHelmMolView} from '@datagrok-libraries/hwe';
25
+ import type {CanvasBounds, IMonomerLibBaseLike} from '@datagrok-libraries/hwe';
27
26
 
28
- import {_package, getHelmService} from '../package';
27
+ import {getHoveredMonomerFromEditorMol, getSeqMonomerFromHelmAtom} from './get-hovered';
29
28
 
30
- export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProps, HelmAux> {
31
- private _auxList: Map<string, HelmAux | null>;
29
+ import {_package} from '../package';
30
+
31
+ /** Per-cell render bookkeeping for hover hit-testing + the highlight overlay. */
32
+ type HelmCellAux = {
33
+ /** Laid-out molecule as a legacy-shaped view (atoms[].p in model space). */
34
+ molView: HelmMol;
35
+ /** Tight model-space bbox of the drawn content. */
36
+ bBox: DG.Rect;
37
+ /** Absolute (device-pixel) draw box the mol was painted into. */
38
+ dBox: DG.Rect;
39
+ /** Cell height in device pixels (single-atom hover threshold). */
40
+ cellHDev: number;
41
+ };
42
+
43
+ export class HelmGridCellRendererBack extends CellRendererBackBase<string> {
44
+ /**
45
+ * Compat shim for the `measureCellRenderer` benchmark: hwe renders
46
+ * synchronously with an internal LRU parse/layout cache, so this is always
47
+ * `true` (the benchmark then waits on `grid.onAfterDrawContent`).
48
+ */
49
+ public readonly cacheEnabled: boolean = true;
32
50
 
33
51
  private sysMonomerLib: IMonomerLibBase | null = null;
34
52
  private helmHelper: IHelmHelper | null = null;
35
- private helmRenderService: HelmServiceBase | null = null;
36
53
 
37
- // eslint-disable-next-line max-len
38
- private readonly uuid: string = wu.repeat(1).map(() => Math.floor((Math.random() * 36)).toString(36)).take(4).toArray().join('');
54
+ /** hwe service per monomer-library source (a cell may carry an overridden lib). */
55
+ private readonly serviceByLib: Map<string, HweHelmService> = new Map();
56
+ /** Per-cell-value render bookkeeping (hover + highlight). */
57
+ private auxList: Map<string, HelmCellAux> = new Map();
39
58
 
40
- constructor(
41
- gridCol: DG.GridColumn | null,
42
- tableCol: DG.Column<string>,
43
- ) {
44
- super(gridCol, tableCol, _package.logger, true);
59
+ constructor(gridCol: DG.GridColumn | null, tableCol: DG.Column<string>) {
60
+ super(gridCol, tableCol, _package.logger);
45
61
  }
46
62
 
47
63
  public async init(): Promise<void> {
@@ -53,12 +69,13 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
53
69
  (async () => {
54
70
  this.helmHelper = await getHelmHelper();
55
71
  })(),
56
- (async () => {
57
- this.helmRenderService = await getHelmService();
58
- })(),
59
72
  ]);
60
73
 
61
74
  this.subs.push(this.sysMonomerLib!.onChanged.subscribe(() => {
75
+ // A library change invalidates every cached service + render.
76
+ for (const svc of this.serviceByLib.values()) svc.destroy();
77
+ this.serviceByLib.clear();
78
+ this.auxList.clear();
62
79
  this.dirty = true;
63
80
  this.invalidateGrid();
64
81
  }));
@@ -70,6 +87,13 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
70
87
  this.invalidateGrid();
71
88
  }
72
89
 
90
+ protected override destroy(): void {
91
+ for (const svc of this.serviceByLib.values()) svc.destroy();
92
+ this.serviceByLib.clear();
93
+ this.auxList.clear();
94
+ super.destroy();
95
+ }
96
+
73
97
  private handleHighlightEvent(args: MacromoleculeHighlightEventArgs): void {
74
98
  if (!args || !this.tableCol || !this.tableCol.dataFrame) return;
75
99
  if (args.columnName !== this.tableCol.name) return;
@@ -102,120 +126,94 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
102
126
  return this.tableCol.temp[MmcrTemps.overriddenLibrary] ?? this.sysMonomerLib;
103
127
  }
104
128
 
129
+ /** Get (or lazily build) the hwe service bound to `lib`, keyed by its source. */
130
+ private getService(lib: IMonomerLibBase): HweHelmService {
131
+ const key = lib.source;
132
+ let svc = this.serviceByLib.get(key);
133
+ if (svc === undefined) {
134
+ svc = new HweHelmService({monomerLib: bridgeMonomerLib(lib as unknown as IMonomerLibBaseLike)});
135
+ this.serviceByLib.set(key, svc);
136
+ }
137
+ return svc;
138
+ }
139
+
105
140
  protected override reset(): void {
106
- const logPrefix = `${this.toLog()}.reset()`;
107
- this.logger.debug(`${logPrefix}, start`);
108
141
  super.reset();
109
- this._auxList = new Map<string, HelmAux | null>();
142
+ this.auxList = new Map<string, HelmCellAux>();
110
143
  this.invalidateGrid();
111
- this.logger.debug(`${logPrefix}, end`);
112
144
  }
113
145
 
114
- protected override getRenderService(): RenderServiceBase<HelmProps, HelmAux> | null {
115
- return this.helmRenderService;
116
- }
117
-
118
- protected override getRenderTaskProps(
119
- gridCell: DG.GridCell, backColor: number, width: number, height: number,
120
- ): HelmProps {
121
- const monomerLib = this.getMonomerLib();
122
- return new HelmProps(gridCell.cell.value, monomerLib, backColor, width, height);
123
- }
146
+ /** Synchronous paint straight into the grid canvas via hwe `renderToCanvas`. */
147
+ public render(
148
+ g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
149
+ gridCell: DG.GridCell, _cellStyle: DG.GridCellStyle,
150
+ ): void {
151
+ const helm = gridCell.cell?.value;
152
+ if (!helm || this.sysMonomerLib === null) return;
153
+ if (w < 5 || h < 5) return;
124
154
 
125
- protected override storeAux(gridCell: DG.GridCell, aux: HelmAux): void {
126
- const logPrefix = `${this.toLog()}.storeAux()`;
127
- this.logger.debug(`${logPrefix}, start`);
128
- if (!!gridCell.cell?.value)
129
- this._auxList.set(gridCell.cell.value, aux);
130
- }
155
+ const dpr = window.devicePixelRatio;
156
+ const svc = this.getService(this.getMonomerLib());
131
157
 
132
- /** Renders cell from image data (cache), returns true to update the cell by service.
133
- * @param gridCellBounds {DG.Rect} Grid cell bounds
134
- */
135
- protected override renderCellImageData(
136
- gridCtx: CanvasRenderingContext2D, gridCellBounds: DG.Rect, gridCell: DG.GridCell, cellImageData: ImageData,
137
- ): boolean {
138
- // super.renderCellImageData(gridCtx, gridCellBounds, gridCell, cellImageData);
139
- // return true;
158
+ g.save();
159
+ try {
160
+ // The grid canvas works in device pixels after resetTransform(); use the
161
+ // cell's own bounds when painting onto the grid's main canvas (robust to
162
+ // scroll), otherwise the passed x/y (off-screen tooltip canvas, etc.).
163
+ g.resetTransform();
164
+ const onGrid = !!(this.gridCol?.dart && this.gridCol.grid?.canvas === g.canvas);
165
+ const bx = (onGrid ? gridCell.bounds.x : x) * dpr;
166
+ const by = (onGrid ? gridCell.bounds.y : y) * dpr;
167
+ const bounds: CanvasBounds = {x: bx, y: by, width: w * dpr, height: h * dpr};
168
+
169
+ // No backColor → the grid keeps its own cell background (selection, etc.).
170
+ // maxScale: Infinity → the drawing scales UP to fill the cell (hwe's
171
+ // default caps at native size, leaving small molecules tiny in big cells).
172
+ // showIds:false → no continuous-id numbers (keeps the grid uncluttered).
173
+ // showAnnotations:true → still draw the 5'/3' direction + ss/as strand-type
174
+ // markers; those are gated separately from the id numbers.
175
+ const res = svc.renderToCanvas(g, helm, bounds, {
176
+ maxScale: Infinity, showIds: false, showAnnotations: true,
177
+ });
140
178
 
141
- const gcb = gridCellBounds;
142
- const dpr = window.devicePixelRatio;
143
- if (!gridCell.cell?.value)
144
- return false;
145
- const aux = this._auxList.get(gridCell.cell.value);
146
- if (!aux)
147
- return true;
148
-
149
- const [cellWidth, cellHeight] = [gcb.width * dpr - 2, gcb.height * dpr - 2];
150
- const cellDScale = Math.min(0.95 * cellWidth / aux.dBox.width, 0.95 * cellHeight / aux.dBox.height);
151
- const [cellDWidth, cellDHeight] = [cellDScale * aux.dBox.width, cellDScale * aux.dBox.height];
152
- const cellDBox = new DG.Rect((cellWidth - cellDWidth) / 2, (cellHeight - cellDHeight) / 2, cellDWidth, cellDHeight);
153
-
154
-
155
- // Draw cell image data to scale it with drawImage() while transform()
156
- const cellCanvas = ui.canvas(cellImageData.width, cellImageData.height);
157
- const cellCtx = cellCanvas.getContext('2d')!;
158
- cellCtx.putImageData(cellImageData, 0, 0);
159
-
160
- // // Get bbox canvas
161
- // const bBoxImageData = cellCtx.getImageData(aux.bBox.x, aux.bBox.y, aux.bBox.width, aux.bBox.height);
162
- // const bBoxCanvas = ui.canvas(aux.bBox.width, aux.bBox.height);
163
- // const bBoxCtx = bBoxCanvas.getContext('2d')!;
164
- // bBoxCtx.putImageData(bBoxImageData, 0, 0);
165
- //
166
- const fitCanvasWidth = gridCellBounds.width * dpr - 2;
167
- const fitCanvasHeight = gridCellBounds.height * dpr - 2;
168
- //
169
- // const bBoxRatio = Math.max(aux.bBox.width / aux.cBox.width, aux.bBox.height / aux.cBox.height);
170
- // const bBoxFullWidth = aux.bBox.width / bBoxRatio;
171
- // const bBoxFullHeight = aux.bBox.height / bBoxRatio;
172
- //
173
- // const fitScale = Math.min(fitCanvasWidth / bBoxFullWidth, fitCanvasHeight / bBoxFullHeight);
174
- //
175
- // // Relative shift of bbox center to cbox center
176
- // const bBoxShiftHR = (aux.bBox.left + aux.bBox.width / 2 - aux.cBox.width / 2) / aux.cBox.width;
177
- // const bBoxShiftVR = (aux.bBox.top + aux.bBox.height / 2 - aux.cBox.height / 2) / aux.cBox.height;
178
- //
179
- // const bBoxFitLeft = fitCanvasWidth / 2 - bBoxCanvas.width * fitScale * (1 - 2 * bBoxShiftHR) / 2;
180
- // const bBoxFitTop = fitCanvasHeight / 2 - bBoxCanvas.height * fitScale * (1 - 2 * bBoxShiftVR) / 2;
181
- //
182
- const fitCanvas = ui.canvas(fitCanvasWidth, fitCanvasHeight);
183
- const fitCtx = fitCanvas.getContext('2d')!;
184
- // fitCtx.fillStyle = '#FFFFA0';
185
- // fitCtx.fillRect(0, 0, fitCanvasWidth, fitCanvasHeight);
186
- // fitCtx.transform(fitScale, 0, 0, fitScale, bBoxFitLeft, bBoxFitTop);
187
- // fitCtx.drawImage(bBoxCanvas, 0, 0); // draw with scale transform
188
- fitCtx.drawImage(cellCanvas,
189
- aux.dBox.x, aux.dBox.y, aux.dBox.width, aux.dBox.height,
190
- cellDBox.x, cellDBox.y, cellDBox.width, cellDBox.height);
191
-
192
- this.drawHighlightOverlay(fitCtx, aux, cellDBox, gridCell.tableRowIndex);
193
-
194
- const fitCanvasData = fitCtx.getImageData(0, 0, fitCanvasWidth, fitCanvasHeight);
195
- this.renderOnGrid(gridCtx, gridCellBounds, gridCell, fitCanvasData);
196
-
197
- return aux.cBox.width != cellWidth || aux.cBox.height != cellHeight; // request rendering
179
+ const aux: HelmCellAux = {
180
+ molView: buildHelmMolView(res.mol) as unknown as HelmMol,
181
+ bBox: new DG.Rect(res.bbox.x, res.bbox.y, res.bbox.width, res.bbox.height),
182
+ dBox: new DG.Rect(res.drawBox.x, res.drawBox.y, res.drawBox.width, res.drawBox.height),
183
+ cellHDev: h * dpr,
184
+ };
185
+ this.auxList.set(helm, aux);
186
+
187
+ // drawMolToContext restores its own transform, so we are back in
188
+ // device-pixel space here for the overlay.
189
+ this.drawHighlightOverlay(g, aux, gridCell.tableRowIndex);
190
+ } catch (err: any) {
191
+ const [errMsg, errStack] = errInfo(err);
192
+ this.logger.error(errMsg, undefined, errStack);
193
+ } finally {
194
+ g.restore();
195
+ }
196
+ this._onRendered.next();
198
197
  }
199
198
 
200
- // Overlays a translucent ring around each highlighted monomer on top of the already-drawn
201
- // helm image. Highlight data comes from `tableCol.temp[MACROMOLECULE_HIGHLIGHT_TEMP]` for the given
202
- // row. The ring is sized from the median bond length so it sits just outside the monomer glyph.
199
+ // Overlays a translucent ring around each highlighted monomer on top of the
200
+ // already-drawn helm. Highlight data comes from
201
+ // `tableCol.temp[MACROMOLECULE_HIGHLIGHT_TEMP]` for the given row. Atom
202
+ // positions (model space) map to device pixels via dBox / bBox.
203
203
  private drawHighlightOverlay(
204
- ctx: CanvasRenderingContext2D, aux: HelmAux, cellDBox: DG.Rect, rowIdx: number | null,
204
+ ctx: CanvasRenderingContext2D, aux: HelmCellAux, rowIdx: number | null,
205
205
  ): void {
206
206
  const entry = this.getHighlightForRow(rowIdx);
207
207
  if (!entry || !entry.monomers || entry.monomers.length === 0) return;
208
- const atoms = aux.mol?.atoms;
208
+ const atoms = aux.molView?.atoms;
209
209
  if (!atoms || atoms.length === 0) return;
210
210
  if (aux.bBox.width <= 0 || aux.bBox.height <= 0) return;
211
211
 
212
- const sx = cellDBox.width / aux.bBox.width;
213
- const sy = cellDBox.height / aux.bBox.height;
212
+ const sx = aux.dBox.width / aux.bBox.width;
213
+ const sy = aux.dBox.height / aux.bBox.height;
214
214
  const sAvg = (sx + sy) / 2;
215
215
 
216
- // Estimate monomer glyph radius in SVG space from bonds, fall back to atom-density heuristic.
217
- const svgMonomerR = this.estimateMonomerRadiusSvg(aux);
218
- // Draw ring just outside the glyph: ~1.05× glyph radius.
216
+ const svgMonomerR = this.estimateMonomerRadiusModel(aux);
219
217
  const markerR = Math.max(6, svgMonomerR * sAvg * 0.7);
220
218
  const lineWidth = Math.max(1.5, markerR * 0.35);
221
219
 
@@ -230,9 +228,8 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
230
228
  for (const idx of entry.monomers) {
231
229
  const a = atoms[idx];
232
230
  if (!a || !a.p) continue;
233
- const fx = cellDBox.x + (a.p.x - aux.bBox.x) * sx;
234
- const fy = cellDBox.y + (a.p.y - aux.bBox.y) * sy;
235
- // Stroke ring with translucent fill — ring sits outside monomer, interior tint is subtle.
231
+ const fx = aux.dBox.x + (a.p.x - aux.bBox.x) * sx;
232
+ const fy = aux.dBox.y + (a.p.y - aux.bBox.y) * sy;
236
233
  ctx.beginPath();
237
234
  ctx.arc(fx, fy, markerR, 0, Math.PI * 2);
238
235
  ctx.fill();
@@ -243,11 +240,11 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
243
240
  }
244
241
  }
245
242
 
246
- // Best-effort monomer glyph radius in SVG (bBox) coordinates. Uses the median bond length when
247
- // bonds are available (monomer glyph width ≈ bond length), otherwise falls back to an area-
248
- // based density estimate from bBox / atom count.
249
- private estimateMonomerRadiusSvg(aux: HelmAux): number {
250
- const bonds = (aux.mol as any)?.bonds as Array<{a1?: {p?: {x: number, y: number}}, a2?: {p?: {x: number, y: number}}}> | undefined;
243
+ // Best-effort monomer glyph radius in model (bBox) coordinates from the median
244
+ // bond length (glyph width ≈ bond length), else an area-density estimate.
245
+ private estimateMonomerRadiusModel(aux: HelmCellAux): number {
246
+ const bonds = (aux.molView as any)?.bonds as
247
+ Array<{a1?: {p?: {x: number, y: number}}, a2?: {p?: {x: number, y: number}}}> | undefined;
251
248
  const lens: number[] = [];
252
249
  if (bonds && bonds.length > 0) {
253
250
  for (const b of bonds) {
@@ -258,18 +255,16 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
258
255
  }
259
256
  }
260
257
  if (lens.length > 0) {
261
- lens.sort((x, y) => x - y);
262
- const median = lens[Math.floor(lens.length / 2)];
263
- return median * 0.55; // glyph radius ≈ half the bond length
258
+ lens.sort((p, q) => p - q);
259
+ return lens[Math.floor(lens.length / 2)] * 0.55;
264
260
  }
265
- const n = Math.max(1, aux.mol?.atoms?.length ?? 1);
266
- const density = Math.sqrt((aux.bBox.width * aux.bBox.height) / n);
267
- return density * 0.45;
261
+ const n = Math.max(1, aux.molView?.atoms?.length ?? 1);
262
+ return Math.sqrt((aux.bBox.width * aux.bBox.height) / n) * 0.45;
268
263
  }
269
264
 
270
265
  onMouseMove(gridCell: DG.GridCell, e: MouseEvent): void {
271
- if (!gridCell.cell?.value || !this._auxList || !!e.buttons) return;
272
- const aux = this._auxList.get(gridCell.cell.value);
266
+ if (!gridCell.cell?.value || !!e.buttons) return;
267
+ const aux = this.auxList.get(gridCell.cell.value);
273
268
  if (!aux) return;
274
269
 
275
270
  const logPrefix = `${this.toLog()}.onMouseMove()`;
@@ -279,15 +274,21 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
279
274
  const cX = (e.offsetX - gcb.x) * dpr;
280
275
  const cY = (e.offsetY - gcb.y) * dpr;
281
276
 
282
- const bX = aux.bBox.x + (cX - aux.dBox.x) * aux.bBox.width / aux.dBox.width;
283
- const bY = aux.bBox.y + (cY - aux.dBox.y) * aux.bBox.height / aux.dBox.height;
277
+ // Map the cursor (device px, relative to the cell) into model space using
278
+ // the absolute draw box. dBox is absolute, so subtract the cell origin.
279
+ const dboxRelX = aux.dBox.x - gcb.x * dpr;
280
+ const dboxRelY = aux.dBox.y - gcb.y * dpr;
281
+ const mX = aux.bBox.x + (cX - dboxRelX) * aux.bBox.width / aux.dBox.width;
282
+ const mY = aux.bBox.y + (cY - dboxRelY) * aux.bBox.height / aux.dBox.height;
283
+ // Single-atom hover threshold (0.35·cellHeight in the legacy) mapped to model space.
284
+ const cellHModel = aux.cellHDev * aux.bBox.height / aux.dBox.height;
284
285
 
285
- const editorMol: Mol<HelmType, IHelmBio> | null = aux.mol; // in bBox world
286
+ const editorMol: Mol<HelmType, IHelmBio> | null = aux.molView as unknown as Mol<HelmType, IHelmBio>;
286
287
  if (!editorMol) {
287
288
  this.logger.warning(`${logPrefix}, editorMol of the cell not found.`);
288
- return; // The gridCell is not rendered yet
289
+ return;
289
290
  }
290
- const hoveredAtom = getHoveredMonomerFromEditorMol(bX, bY, editorMol, gridCell.bounds.height);
291
+ const hoveredAtom = getHoveredMonomerFromEditorMol(mX, mY, aux.molView, cellHModel);
291
292
 
292
293
  let seqMonomer: ISeqMonomer | null = null;
293
294
  if (hoveredAtom && this.helmHelper && gridCell.tableRowIndex != null) {
@@ -299,7 +300,6 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
299
300
  ui.divText('Monomer library is not available');
300
301
  ui.tooltip.show(tooltipEl, e.x + 16, e.y + 16);
301
302
  } else {
302
- // Tooltip for missing monomers
303
303
  ui.tooltip.hide();
304
304
  }
305
305
  execMonomerHoverLinks(gridCell, seqMonomer);
@@ -312,14 +312,6 @@ export class HelmGridCellRendererBack extends CellRendererBackAsyncBase<HelmProp
312
312
  execMonomerHoverLinks(gridCell, null);
313
313
  }
314
314
 
315
- // public override render(g: CanvasRenderingContext2D, x: number, y: number, w: number, h: number,
316
- // gridCell: DG.GridCell, cellStyle: DG.GridCellStyle
317
- // ) {
318
- // super.render(g, x, y, w, h, gridCell, cellStyle);
319
- // }
320
-
321
- // -- Handle events --
322
-
323
315
  static getOrCreate(gridCell: DG.GridCell): HelmGridCellRendererBack {
324
316
  const [gridCol, tableCol, temp] =
325
317
  getGridCellColTemp<string, HelmGridCellRendererBack>(gridCell);
@@ -343,7 +335,6 @@ export class HelmGridCellRenderer extends DG.GridCellRenderer {
343
335
  get defaultHeight(): number | null { return 100; }
344
336
 
345
337
  override onMouseMove(gridCell: DG.GridCell, e: MouseEvent) {
346
- const logPrefix = `Helm: HelmGridCellRenderer.onMouseMove()`;
347
338
  try {
348
339
  HelmGridCellRendererBack.getOrCreate(gridCell).onMouseMove(gridCell, e);
349
340
  } catch (err: any) {
@@ -353,7 +344,6 @@ export class HelmGridCellRenderer extends DG.GridCellRenderer {
353
344
  }
354
345
 
355
346
  override onMouseLeave(gridCell: DG.GridCell, e: MouseEvent) {
356
- const logPrefix = `Helm: HelmGridCellRenderer.onMouseLeave()`;
357
347
  try {
358
348
  HelmGridCellRendererBack.getOrCreate(gridCell).onMouseLeave(gridCell, e);
359
349
  } catch (err: any) {
@@ -3,7 +3,6 @@ import * as ui from 'datagrok-api/ui';
3
3
  import * as DG from 'datagrok-api/dg';
4
4
 
5
5
  import {IMonomerLib} from '@datagrok-libraries/bio/src/types/monomer-library';
6
- import {OrgHelmModule, ScilModule} from '../types';
7
6
 
8
7
  import {
9
8
  RGROUP_CAP_GROUP_NAME,
@@ -17,9 +16,6 @@ import {
17
16
  } from '../constants';
18
17
 
19
18
 
20
- declare const scil: ScilModule;
21
- declare const org: OrgHelmModule;
22
-
23
19
  // Global flag is for replaceAll
24
20
  const helmGapStartRe = /\{(\*\.)+/g;
25
21
  const helmGapIntRe = /\.(\*\.)+/g;
@@ -48,7 +44,7 @@ export function parseHelm(s: string): string[] {
48
44
  const sections = split(s, '$');
49
45
  s = sections[0];
50
46
  const monomers = [];
51
- if (!scil.Utils.isNullOrEmpty(s)) {
47
+ if (!(s == null || s === '')) {
52
48
  const seqs = split(s, '|');
53
49
  for (let i = 0; i < seqs.length; ++i) {
54
50
  const e = detachAnnotation(seqs[i]);
@@ -205,7 +201,7 @@ function detachAnnotation(s: string) {
205
201
 
206
202
  function _detachAppendix(s: string, c: string) {
207
203
  let tag = null;
208
- if (scil.Utils.endswith(s, c)) {
204
+ if (s.endsWith(c)) {
209
205
  let p = s.length - 1;
210
206
  while (p > 0) {
211
207
  p = s.lastIndexOf(c, p - 1);
@@ -224,7 +220,7 @@ function _detachAppendix(s: string, c: string) {
224
220
  }
225
221
 
226
222
  function unescape(s: string) {
227
- if (scil.Utils.isNullOrEmpty(s))
223
+ if (s == null || s === '')
228
224
  return s;
229
225
 
230
226
  return s.replace(/[\\]./g, function(m) {