@haniffalab/cherita-react 1.3.0-dev.2025-06-04.0123fe8a → 1.3.0-dev.2025-06-05.2b7d4704

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.
@@ -0,0 +1,198 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+
4
+ <svg
5
+ version="1.1"
6
+ id="svg1"
7
+ width="299.52322"
8
+ height="282.82245"
9
+ viewBox="0 0 299.52322 282.82245"
10
+ sodipodi:docname="umap.svg"
11
+ inkscape:version="1.4 (1:1.4+202410161351+e7c3feb100)"
12
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ xmlns:svg="http://www.w3.org/2000/svg">
16
+ <defs
17
+ id="defs1" />
18
+ <sodipodi:namedview
19
+ id="namedview1"
20
+ pagecolor="#ffffff"
21
+ bordercolor="#000000"
22
+ borderopacity="0.25"
23
+ inkscape:showpageshadow="2"
24
+ inkscape:pageopacity="0.0"
25
+ inkscape:pagecheckerboard="0"
26
+ inkscape:deskcolor="#d1d1d1"
27
+ inkscape:zoom="0.51375727"
28
+ inkscape:cx="883.68579"
29
+ inkscape:cy="221.89467"
30
+ inkscape:window-width="1854"
31
+ inkscape:window-height="1011"
32
+ inkscape:window-x="0"
33
+ inkscape:window-y="0"
34
+ inkscape:window-maximized="1"
35
+ inkscape:current-layer="g1" />
36
+ <g
37
+ inkscape:groupmode="layer"
38
+ inkscape:label="Image"
39
+ id="g1"
40
+ transform="translate(-61.989251,-346.50722)">
41
+ <circle
42
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
43
+ id="path1"
44
+ cx="151.91397"
45
+ cy="358.70969"
46
+ r="11.870968" />
47
+ <circle
48
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
49
+ id="path1-3"
50
+ cx="100.01968"
51
+ cy="380.43903"
52
+ r="11.870968" />
53
+ <circle
54
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
55
+ id="path1-1"
56
+ cx="122.81537"
57
+ cy="406.75085"
58
+ r="11.870968" />
59
+ <circle
60
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
61
+ id="path1-36"
62
+ cx="157.06268"
63
+ cy="398.81537"
64
+ r="11.870968" />
65
+ <circle
66
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
67
+ id="path1-18"
68
+ cx="80.761612"
69
+ cy="421.50354"
70
+ r="11.870968" />
71
+ <circle
72
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
73
+ id="path1-2"
74
+ cx="108.28849"
75
+ cy="444.78311"
76
+ r="11.870968" />
77
+ <circle
78
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
79
+ id="path1-22"
80
+ cx="142.9229"
81
+ cy="445.9874"
82
+ r="11.870968" />
83
+ <circle
84
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
85
+ id="path1-6"
86
+ cx="74.191719"
87
+ cy="466.75085"
88
+ r="11.870968" />
89
+ <circle
90
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
91
+ id="path1-19"
92
+ cx="110.5143"
93
+ cy="487.65405"
94
+ r="11.870968" />
95
+ <circle
96
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
97
+ id="path1-5"
98
+ cx="147.77235"
99
+ cy="484.92288"
100
+ r="11.870968" />
101
+ <circle
102
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
103
+ id="path1-0"
104
+ cx="126.1487"
105
+ cy="521.36377"
106
+ r="11.870968" />
107
+ <circle
108
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
109
+ id="path1-61"
110
+ cx="294.42828"
111
+ cy="370.49277"
112
+ r="11.870968" />
113
+ <circle
114
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
115
+ id="path1-65"
116
+ cx="260.76163"
117
+ cy="401.9444"
118
+ r="11.870968" />
119
+ <circle
120
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
121
+ id="path1-4"
122
+ cx="297.76163"
123
+ cy="419.99814"
124
+ r="11.870968" />
125
+ <circle
126
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
127
+ id="path1-7"
128
+ cx="329.98743"
129
+ cy="394.70782"
130
+ r="11.870968" />
131
+ <circle
132
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
133
+ id="path1-78"
134
+ cx="349.31"
135
+ cy="436.11642"
136
+ r="11.870968" />
137
+ <circle
138
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
139
+ id="path1-31"
140
+ cx="314.79388"
141
+ cy="462.32074"
142
+ r="11.870968" />
143
+ <circle
144
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
145
+ id="path1-68"
146
+ cx="293.4928"
147
+ cy="495.1702"
148
+ r="11.870968" />
149
+ <circle
150
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
151
+ id="path1-49"
152
+ cx="267.01968"
153
+ cy="452.15945"
154
+ r="11.870968" />
155
+ <circle
156
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
157
+ id="path1-71"
158
+ cx="216.14873"
159
+ cy="530.72931"
160
+ r="11.870968" />
161
+ <circle
162
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
163
+ id="path1-26"
164
+ cx="252.67558"
165
+ cy="538.61108"
166
+ r="11.870968" />
167
+ <circle
168
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
169
+ id="path1-59"
170
+ cx="258.267"
171
+ cy="579.61108"
172
+ r="11.870968" />
173
+ <circle
174
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
175
+ id="path1-17"
176
+ cx="220.66486"
177
+ cy="574.41748"
178
+ r="11.870968" />
179
+ <circle
180
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
181
+ id="path1-9"
182
+ cx="184.00893"
183
+ cy="559.96588"
184
+ r="11.870968" />
185
+ <circle
186
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
187
+ id="path1-365"
188
+ cx="185.79387"
189
+ cy="598.26697"
190
+ r="11.870968" />
191
+ <circle
192
+ style="opacity:0.994362;fill:#000000;fill-opacity:1;stroke:#070707;stroke-width:0.663"
193
+ id="path1-8"
194
+ cx="224.85838"
195
+ cy="617.1272"
196
+ r="11.870968" />
197
+ </g>
198
+ </svg>
@@ -0,0 +1,50 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <svg
3
+ viewBox="0 0 36.994598 39.994202"
4
+ x="0px"
5
+ y="0px"
6
+ version="1.1"
7
+ id="svg4"
8
+ sodipodi:docname="violin.svg"
9
+ inkscape:version="1.4 (1:1.4+202410161351+e7c3feb100)"
10
+ width="36.994598"
11
+ height="39.994202"
12
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ xmlns:svg="http://www.w3.org/2000/svg">
16
+ <defs
17
+ id="defs4" />
18
+ <sodipodi:namedview
19
+ id="namedview4"
20
+ pagecolor="#ffffff"
21
+ bordercolor="#000000"
22
+ borderopacity="0.25"
23
+ inkscape:showpageshadow="2"
24
+ inkscape:pageopacity="0.0"
25
+ inkscape:pagecheckerboard="0"
26
+ inkscape:deskcolor="#d1d1d1"
27
+ inkscape:zoom="5.757143"
28
+ inkscape:cx="17.369727"
29
+ inkscape:cy="35.781637"
30
+ inkscape:window-width="1854"
31
+ inkscape:window-height="1011"
32
+ inkscape:window-x="0"
33
+ inkscape:window-y="0"
34
+ inkscape:window-maximized="1"
35
+ inkscape:current-layer="svg4" />
36
+ <g
37
+ class="secondary"
38
+ id="g2"
39
+ transform="translate(-12.0029,-8.0029)">
40
+ <path
41
+ d="M 19.9971,24.5 A 6.3078,6.3078 0 0 0 18.5732,20.8389 7.1479,7.1479 0 0 1 16.9971,16.5 V 16.0029 H 16.0029 V 16.5 a 7.1479,7.1479 0 0 1 -1.5761,4.3389 6.3078,6.3078 0 0 0 -1.4239,3.6611 12.4967,12.4967 0 0 1 -0.4853,3.38 13.5076,13.5076 0 0 0 -0.5147,3.62 6.3078,6.3078 0 0 0 1.4239,3.6611 7.1479,7.1479 0 0 1 1.5761,4.3389 19.2486,19.2486 0 0 0 0.5664,4.7246 13.6883,13.6883 0 0 1 0.4336,3.2754 v 0.4971 h 0.9942 V 47.5 A 13.6883,13.6883 0 0 1 17.4307,44.2246 19.2486,19.2486 0 0 0 17.9971,39.5 7.1479,7.1479 0 0 1 19.5732,35.1611 6.3078,6.3078 0 0 0 20.9971,31.5 13.5076,13.5076 0 0 0 20.4824,27.88 12.4967,12.4967 0 0 1 19.9971,24.5 Z"
42
+ id="path1" />
43
+ <path
44
+ d="M 34.6436,12.6963 C 32.8506,11.5537 30.9971,10.3711 30.9971,8.5 V 8.0029 H 30.0029 V 8.5 c 0,1.8711 -1.8535,3.0537 -3.6465,4.1963 -1.7246,1.1006 -3.3535,2.1387 -3.3535,3.8037 0,1.6152 1.2188,2.7031 2.3975,3.7549 1.2793,1.1426 2.6025,2.3242 2.6025,4.2451 a 18.1508,18.1508 0 0 1 -0.542,4.5068 14.5,14.5 0 0 0 -0.458,3.4932 6.038,6.038 0 0 0 1.6,3.7979 5.179,5.179 0 0 1 1.4,3.2021 v 0.4971 h 0.9942 V 39.5 a 5.179,5.179 0 0 1 1.4,-3.2021 6.038,6.038 0 0 0 1.6,-3.7979 14.5,14.5 0 0 0 -0.458,-3.4932 18.1508,18.1508 0 0 1 -0.542,-4.5068 c 0,-1.9209 1.3232,-3.1025 2.6025,-4.2451 1.1787,-1.0518 2.3975,-2.14 2.3975,-3.7549 0,-1.665 -1.6289,-2.7031 -3.3535,-3.8037 z"
45
+ id="path3" />
46
+ <path
47
+ d="M 47.3975,35.7021 A 5.179,5.179 0 0 1 45.9975,32.5 14.5,14.5 0 0 0 45.5395,29.0068 18.1508,18.1508 0 0 1 44.9975,24.5 V 24.0029 H 44.0033 V 24.5 a 18.1508,18.1508 0 0 1 -0.542,4.5068 14.5,14.5 0 0 0 -0.458,3.4932 5.179,5.179 0 0 1 -1.4,3.2021 6.038,6.038 0 0 0 -1.6,3.7979 c 0,1.582 0.9717,2.667 1.9121,3.7158 1.0264,1.1455 2.0879,2.3311 2.0879,4.2842 v 0.4971 h 0.9942 V 47.5 c 0,-1.9531 1.0615,-3.1387 2.0879,-4.2842 0.94,-1.0488 1.9121,-2.1338 1.9121,-3.7158 a 6.038,6.038 0 0 0 -1.6,-3.7979 z"
48
+ id="path2" />
49
+ </g>
50
+ </svg>
@@ -44,7 +44,7 @@ const INITIAL_VIEW_STATE = {
44
44
  function Scatterplot(_ref) {
45
45
  var _settings$selectedObs3, _features$features2, _obsmData$serverError, _xData$serverError, _obsData$serverError, _labelObsData$serverE, _settings$selectedVar, _settings$selectedObs4, _obsmData$data;
46
46
  let {
47
- radius = 30,
47
+ radius = null,
48
48
  setShowObs,
49
49
  setShowVars,
50
50
  isFullscreen = false
@@ -69,6 +69,7 @@ function Scatterplot(_ref) {
69
69
  values: [],
70
70
  sliceValues: []
71
71
  });
72
+ const [radiusScale, setRadiusScale] = (0, _react.useState)(radius || 1);
72
73
 
73
74
  // EditableGeoJsonLayer
74
75
  const [mode, setMode] = (0, _react.useState)(() => _editModes.ViewMode);
@@ -85,6 +86,15 @@ function Scatterplot(_ref) {
85
86
  const labelObsData = (0, _zarrData.useLabelObsData)();
86
87
  // @TODO: assert length of obsmData, xData, obsData is equal
87
88
 
89
+ const getRadiusScale = (0, _react.useCallback)(bounds => {
90
+ if (!!radius) return radius;
91
+ // From 28 degrees ~= 30km -> 30m radius
92
+ const lonDim = bounds[1][0] - bounds[0][0];
93
+ const latDim = bounds[1][1] - bounds[0][1];
94
+ const minDim = Math.min(lonDim, latDim);
95
+ const rs = 0.01 / minDim * 111111;
96
+ return rs;
97
+ }, [radius]);
88
98
  (0, _react.useEffect)(() => {
89
99
  if (!obsmData.isPending && !obsmData.serverError) {
90
100
  var _deckRef$current, _deckRef$current2;
@@ -98,11 +108,13 @@ function Scatterplot(_ref) {
98
108
  const {
99
109
  latitude,
100
110
  longitude,
101
- zoom
111
+ zoom,
112
+ bounds
102
113
  } = mapHelper.fitBounds(obsmData.data, {
103
114
  width: deckRef === null || deckRef === void 0 || (_deckRef$current = deckRef.current) === null || _deckRef$current === void 0 || (_deckRef$current = _deckRef$current.deck) === null || _deckRef$current === void 0 ? void 0 : _deckRef$current.width,
104
115
  height: deckRef === null || deckRef === void 0 || (_deckRef$current2 = deckRef.current) === null || _deckRef$current2 === void 0 || (_deckRef$current2 = _deckRef$current2.deck) === null || _deckRef$current2 === void 0 ? void 0 : _deckRef$current2.height
105
116
  });
117
+ setRadiusScale(getRadiusScale(bounds));
106
118
  setViewState(v => {
107
119
  return _objectSpread(_objectSpread({}, v), {}, {
108
120
  longitude: longitude,
@@ -118,7 +130,7 @@ function Scatterplot(_ref) {
118
130
  });
119
131
  });
120
132
  }
121
- }, [settings.selectedObsm, obsmData.data, obsmData.isPending, obsmData.serverError]);
133
+ }, [settings.selectedObsm, getRadiusScale, obsmData.data, obsmData.isPending, obsmData.serverError]);
122
134
  const getBounds = (0, _react.useCallback)(() => {
123
135
  var _deckRef$current3, _deckRef$current4;
124
136
  const {
@@ -232,7 +244,7 @@ function Scatterplot(_ref) {
232
244
  id: "cherita-layer-scatterplot",
233
245
  pickable: true,
234
246
  data: data.positions,
235
- radiusScale: radius,
247
+ radiusScale: radiusScale,
236
248
  radiusMinPixels: 1,
237
249
  getPosition: d => d,
238
250
  getFillColor: getFillColor,
@@ -275,7 +287,7 @@ function Scatterplot(_ref) {
275
287
  }
276
288
  }
277
289
  })];
278
- }, [data.positions, features, getFillColor, getRadius, mode, radius, selectedFeatureIndexes]);
290
+ }, [data.positions, features, getFillColor, getRadius, mode, radiusScale, selectedFeatureIndexes]);
279
291
  const layers = (0, _react.useDeferredValue)(mode === _editModes.ViewMode ? memoizedLayers.reverse() : memoizedLayers); // draw scatterplot on top of polygons when in ViewMode
280
292
 
281
293
  (0, _react.useEffect)(() => {
@@ -54,7 +54,8 @@ class MapHelper {
54
54
  return {
55
55
  longitude,
56
56
  latitude,
57
- zoom
57
+ zoom,
58
+ bounds
58
59
  };
59
60
  }
60
61
  }
@@ -36,7 +36,7 @@ const INITIAL_VIEW_STATE = {
36
36
  export function Scatterplot(_ref) {
37
37
  var _settings$selectedObs3, _features$features2, _obsmData$serverError, _xData$serverError, _obsData$serverError, _labelObsData$serverE, _settings$selectedVar, _settings$selectedObs4, _obsmData$data;
38
38
  let {
39
- radius = 30,
39
+ radius = null,
40
40
  setShowObs,
41
41
  setShowVars,
42
42
  isFullscreen = false
@@ -61,6 +61,7 @@ export function Scatterplot(_ref) {
61
61
  values: [],
62
62
  sliceValues: []
63
63
  });
64
+ const [radiusScale, setRadiusScale] = useState(radius || 1);
64
65
 
65
66
  // EditableGeoJsonLayer
66
67
  const [mode, setMode] = useState(() => ViewMode);
@@ -77,6 +78,15 @@ export function Scatterplot(_ref) {
77
78
  const labelObsData = useLabelObsData();
78
79
  // @TODO: assert length of obsmData, xData, obsData is equal
79
80
 
81
+ const getRadiusScale = useCallback(bounds => {
82
+ if (!!radius) return radius;
83
+ // From 28 degrees ~= 30km -> 30m radius
84
+ const lonDim = bounds[1][0] - bounds[0][0];
85
+ const latDim = bounds[1][1] - bounds[0][1];
86
+ const minDim = Math.min(lonDim, latDim);
87
+ const rs = 0.01 / minDim * 111111;
88
+ return rs;
89
+ }, [radius]);
80
90
  useEffect(() => {
81
91
  if (!obsmData.isPending && !obsmData.serverError) {
82
92
  var _deckRef$current, _deckRef$current2;
@@ -90,11 +100,13 @@ export function Scatterplot(_ref) {
90
100
  const {
91
101
  latitude,
92
102
  longitude,
93
- zoom
103
+ zoom,
104
+ bounds
94
105
  } = mapHelper.fitBounds(obsmData.data, {
95
106
  width: deckRef === null || deckRef === void 0 || (_deckRef$current = deckRef.current) === null || _deckRef$current === void 0 || (_deckRef$current = _deckRef$current.deck) === null || _deckRef$current === void 0 ? void 0 : _deckRef$current.width,
96
107
  height: deckRef === null || deckRef === void 0 || (_deckRef$current2 = deckRef.current) === null || _deckRef$current2 === void 0 || (_deckRef$current2 = _deckRef$current2.deck) === null || _deckRef$current2 === void 0 ? void 0 : _deckRef$current2.height
97
108
  });
109
+ setRadiusScale(getRadiusScale(bounds));
98
110
  setViewState(v => {
99
111
  return _objectSpread(_objectSpread({}, v), {}, {
100
112
  longitude: longitude,
@@ -110,7 +122,7 @@ export function Scatterplot(_ref) {
110
122
  });
111
123
  });
112
124
  }
113
- }, [settings.selectedObsm, obsmData.data, obsmData.isPending, obsmData.serverError]);
125
+ }, [settings.selectedObsm, getRadiusScale, obsmData.data, obsmData.isPending, obsmData.serverError]);
114
126
  const getBounds = useCallback(() => {
115
127
  var _deckRef$current3, _deckRef$current4;
116
128
  const {
@@ -224,7 +236,7 @@ export function Scatterplot(_ref) {
224
236
  id: "cherita-layer-scatterplot",
225
237
  pickable: true,
226
238
  data: data.positions,
227
- radiusScale: radius,
239
+ radiusScale: radiusScale,
228
240
  radiusMinPixels: 1,
229
241
  getPosition: d => d,
230
242
  getFillColor: getFillColor,
@@ -267,7 +279,7 @@ export function Scatterplot(_ref) {
267
279
  }
268
280
  }
269
281
  })];
270
- }, [data.positions, features, getFillColor, getRadius, mode, radius, selectedFeatureIndexes]);
282
+ }, [data.positions, features, getFillColor, getRadius, mode, radiusScale, selectedFeatureIndexes]);
271
283
  const layers = useDeferredValue(mode === ViewMode ? memoizedLayers.reverse() : memoizedLayers); // draw scatterplot on top of polygons when in ViewMode
272
284
 
273
285
  useEffect(() => {
@@ -47,7 +47,8 @@ export class MapHelper {
47
47
  return {
48
48
  longitude,
49
49
  latitude,
50
- zoom
50
+ zoom,
51
+ bounds
51
52
  };
52
53
  }
53
54
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haniffalab/cherita-react",
3
- "version": "1.3.0-dev.2025-06-04.0123fe8a",
3
+ "version": "1.3.0-dev.2025-06-05.2b7d4704",
4
4
  "author": "Haniffa Lab",
5
5
  "license": "MIT",
6
6
  "keywords": [
@@ -90,7 +90,8 @@
90
90
  "build:babel": "npm run build:esm && npm run build:cjs",
91
91
  "build:scss": "sass --load-path=node_modules src/scss/cherita-bootstrap.scss dist/css/cherita.css",
92
92
  "copy:scss": "cpx 'src/scss/**/*' 'scss'",
93
- "build": "npm run build:babel && npm run build:scss && npm run copy:scss",
93
+ "copy:assets": "cpx 'src/assets/**/*' 'dist/assets'",
94
+ "build": "npm run build:babel && npm run build:scss && npm run copy:scss && npm run copy:assets",
94
95
  "test": "jest --watchAll",
95
96
  "test:ci": "jest --coverage --ci --no-watch",
96
97
  "lint:scss": "stylelint 'src/**/*.scss' --fix",
@@ -126,5 +127,5 @@
126
127
  "url": "https://github.com/haniffalab/cherita-react/issues"
127
128
  },
128
129
  "homepage": "https://github.com/haniffalab/cherita-react#readme",
129
- "prereleaseSha": "0123fe8ae9b9e8cac1b41bc7c5f201a4bbec8214"
130
+ "prereleaseSha": "2b7d4704cf12e0c0f474797aeb9b6b76384f22c2"
130
131
  }