@jbrowse/core 1.6.3 → 1.6.6

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 (56) hide show
  1. package/BaseFeatureWidget/BaseFeatureDetail.js +1 -3
  2. package/BaseFeatureWidget/index.d.ts +1 -1
  3. package/PluginLoader.d.ts +1 -1
  4. package/PluginManager.d.ts +2 -0
  5. package/ReExports/modules.d.ts +2 -0
  6. package/TextSearch/TextSearchManager.d.ts +2 -2
  7. package/assemblyManager/assemblyConfigSchema.d.ts +1 -1
  8. package/assemblyManager/assemblyManager.d.ts +1 -1
  9. package/configuration/index.d.ts +1 -1
  10. package/data_adapters/BaseAdapter.d.ts +2 -1
  11. package/data_adapters/BaseAdapter.js +29 -3
  12. package/data_adapters/CytobandAdapter.d.ts +1 -1
  13. package/package.json +4 -4
  14. package/pluggableElementTypes/RpcMethodType.js +1 -1
  15. package/pluggableElementTypes/models/InternetAccountModel.d.ts +103 -7
  16. package/pluggableElementTypes/models/InternetAccountModel.js +296 -10
  17. package/pluggableElementTypes/models/baseConnectionConfig.d.ts +1 -1
  18. package/pluggableElementTypes/models/baseInternetAccountConfig.d.ts +1 -1
  19. package/pluggableElementTypes/models/baseInternetAccountConfig.js +16 -1
  20. package/pluggableElementTypes/models/baseTrackConfig.d.ts +1 -1
  21. package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.d.ts +1 -0
  22. package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.js +46 -22
  23. package/rpc/BaseRpcDriver.d.ts +4 -4
  24. package/rpc/BaseRpcDriver.js +152 -79
  25. package/rpc/BaseRpcDriver.test.js +64 -43
  26. package/rpc/MainThreadRpcDriver.d.ts +1 -1
  27. package/rpc/MainThreadRpcDriver.js +25 -16
  28. package/rpc/RpcManager.d.ts +1 -1
  29. package/rpc/WebWorkerRpcDriver.d.ts +1 -1
  30. package/rpc/WebWorkerRpcDriver.js +43 -11
  31. package/rpc/configSchema.d.ts +1 -1
  32. package/ui/ErrorMessage.js +23 -8
  33. package/ui/FileSelector/FileSelector.js +1 -1
  34. package/ui/ReturnToImportFormDialog.d.ts +9 -0
  35. package/ui/ReturnToImportFormDialog.js +63 -0
  36. package/ui/Tooltip.d.ts +1 -1
  37. package/ui/Tooltip.js +2 -2
  38. package/ui/index.d.ts +2 -0
  39. package/ui/index.js +18 -0
  40. package/ui/theme.d.ts +8 -0
  41. package/ui/theme.js +9 -0
  42. package/ui/theme.test.js +2 -2
  43. package/util/Base1DViewModel.d.ts +2 -0
  44. package/util/Base1DViewModel.js +9 -0
  45. package/util/index.d.ts +12 -1
  46. package/util/index.js +52 -17
  47. package/util/index.test.js +35 -14
  48. package/util/io/index.d.ts +2 -1
  49. package/util/io/index.js +95 -96
  50. package/util/offscreenCanvasPonyfill.d.ts +1 -0
  51. package/util/offscreenCanvasPonyfill.js +70 -58
  52. package/util/simpleFeature.d.ts +3 -0
  53. package/util/types/index.d.ts +2 -2
  54. package/util/types/index.js +3 -3
  55. package/babel.config.d.ts +0 -15
  56. package/babel.config.js +0 -19
@@ -123,17 +123,49 @@ var WebWorkerRpcDriver = /*#__PURE__*/function (_BaseRpcDriver) {
123
123
 
124
124
  (0, _createClass2.default)(WebWorkerRpcDriver, [{
125
125
  key: "makeWorker",
126
- value: function makeWorker() {
127
- // note that we are making a Rpc.Client connection with a worker pool of
128
- // one for each worker, because we want to do our own state-group-aware
129
- // load balancing rather than using librpc's builtin round-robin
130
- var worker = new WebWorkerHandle({
131
- workers: [new this.WorkerClass()]
132
- }); // send the worker its boot configuration using info from the pluginManager
133
-
134
- worker.workers[0].postMessage(this.workerBootConfiguration);
135
- return worker;
136
- }
126
+ value: function () {
127
+ var _makeWorker = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2() {
128
+ var _this2 = this;
129
+
130
+ var worker, p;
131
+ return _regenerator.default.wrap(function _callee2$(_context2) {
132
+ while (1) {
133
+ switch (_context2.prev = _context2.next) {
134
+ case 0:
135
+ // note that we are making a Rpc.Client connection with a worker pool of
136
+ // one for each worker, because we want to do our own state-group-aware
137
+ // load balancing rather than using librpc's builtin round-robin
138
+ worker = new WebWorkerHandle({
139
+ workers: [new this.WorkerClass()]
140
+ }); // send the worker its boot configuration using info from the pluginManager
141
+
142
+ p = new Promise(function (resolve, reject) {
143
+ worker.workers[0].onmessage = function (e) {
144
+ if (e.data === 'ready') {
145
+ resolve(worker);
146
+ } else if (e.data === 'readyForConfig') {
147
+ worker.workers[0].postMessage(_this2.workerBootConfiguration);
148
+ } else {
149
+ reject();
150
+ }
151
+ };
152
+ });
153
+ return _context2.abrupt("return", p);
154
+
155
+ case 3:
156
+ case "end":
157
+ return _context2.stop();
158
+ }
159
+ }
160
+ }, _callee2, this);
161
+ }));
162
+
163
+ function makeWorker() {
164
+ return _makeWorker.apply(this, arguments);
165
+ }
166
+
167
+ return makeWorker;
168
+ }()
137
169
  }]);
138
170
  return WebWorkerRpcDriver;
139
171
  }(_BaseRpcDriver2.default);
@@ -1,2 +1,2 @@
1
- declare const _default: import("../configuration/configurationSchema").AnyConfigurationSchemaType;
1
+ declare const _default: import("../configuration").AnyConfigurationSchemaType;
2
2
  export default _default;
@@ -32,22 +32,37 @@ var useStyles = (0, _core.makeStyles)(function (theme) {
32
32
  var ErrorMessage = function ErrorMessage(_ref) {
33
33
  var error = _ref.error;
34
34
  var classes = useStyles();
35
+ var snapshotError = '';
35
36
  var str = "".concat(error);
36
- var snapshotError = ''; // best effort to make a better error message than the default
37
- // mobx-state-tree
37
+ var findStr = 'is not assignable';
38
+ var idx = str.indexOf(findStr);
38
39
 
39
- var match = str.match(/.*at path "(.*)" snapshot `(.*)` is not assignable/);
40
+ if (idx !== -1) {
41
+ var trim = str.slice(0, idx + findStr.length); // best effort to make a better error message than the default
42
+ // mobx-state-tree
43
+ // case 1. element has a path
40
44
 
41
- if (match) {
42
- str = "Failed to load element at ".concat(match[1]);
43
- snapshotError = match[2];
45
+ var match = trim.match(/.*at path "(.*)" snapshot `(.*)` is not assignable/m);
46
+
47
+ if (match) {
48
+ str = "Failed to load element at ".concat(match[1], "...Failed element had snapshot");
49
+ snapshotError = match[2];
50
+ } // case 2. element has no path
51
+
52
+
53
+ var match2 = trim.match(/.*snapshot `(.*)` is not assignable/);
54
+
55
+ if (match2) {
56
+ str = "Failed to load element...Failed element had snapshot";
57
+ snapshotError = match2[1];
58
+ }
44
59
  }
45
60
 
46
61
  return /*#__PURE__*/_react.default.createElement("div", {
47
62
  className: classes.message
48
- }, str.slice(0, 10000), snapshotError ? /*#__PURE__*/_react.default.createElement("div", null, "... Failed element had snapshot:", /*#__PURE__*/_react.default.createElement("pre", {
63
+ }, str.slice(0, 10000), snapshotError ? /*#__PURE__*/_react.default.createElement("pre", {
49
64
  className: classes.errorBox
50
- }, JSON.stringify(JSON.parse(snapshotError), null, 2))) : null);
65
+ }, JSON.stringify(JSON.parse(snapshotError), null, 2)) : null);
51
66
  };
52
67
 
53
68
  var _default = ErrorMessage;
@@ -159,7 +159,7 @@ var FileSelector = (0, _mobxReact.observer)(function (props) {
159
159
  value: internetAccountId,
160
160
  "aria-label": name,
161
161
  title: name
162
- }, shorten(toggleContents || name, 5));
162
+ }, typeof toggleContents === 'string' ? shorten(toggleContents, 5) : toggleContents || shorten(name, 5));
163
163
  }), hiddenAccts.length ? /*#__PURE__*/_react.default.createElement(_lab.ToggleButton, {
164
164
  onClick: function onClick(event) {
165
165
  return setAnchorEl(event.target);
@@ -0,0 +1,9 @@
1
+ /// <reference types="react" />
2
+ declare function ReturnToImportFormDialog({ model, handleClose, }: {
3
+ model: {
4
+ clearView: Function;
5
+ };
6
+ handleClose: () => void;
7
+ }): JSX.Element;
8
+ declare const _default: typeof ReturnToImportFormDialog;
9
+ export default _default;
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.default = void 0;
9
+
10
+ var _react = _interopRequireDefault(require("react"));
11
+
12
+ var _mobxReact = require("mobx-react");
13
+
14
+ var _styles = require("@material-ui/core/styles");
15
+
16
+ var _core = require("@material-ui/core");
17
+
18
+ var _Close = _interopRequireDefault(require("@material-ui/icons/Close"));
19
+
20
+ var useStyles = (0, _styles.makeStyles)(function (theme) {
21
+ return {
22
+ closeButton: {
23
+ position: 'absolute',
24
+ right: theme.spacing(1),
25
+ top: theme.spacing(1),
26
+ color: theme.palette.grey[500]
27
+ }
28
+ };
29
+ });
30
+
31
+ function ReturnToImportFormDialog(_ref) {
32
+ var model = _ref.model,
33
+ handleClose = _ref.handleClose;
34
+ var classes = useStyles();
35
+ return /*#__PURE__*/_react.default.createElement(_core.Dialog, {
36
+ maxWidth: "xl",
37
+ open: true,
38
+ onClose: handleClose
39
+ }, /*#__PURE__*/_react.default.createElement(_core.DialogTitle, null, "Reference sequence", handleClose ? /*#__PURE__*/_react.default.createElement(_core.IconButton, {
40
+ className: classes.closeButton,
41
+ onClick: function onClick() {
42
+ return handleClose();
43
+ }
44
+ }, /*#__PURE__*/_react.default.createElement(_Close.default, null)) : null), /*#__PURE__*/_react.default.createElement(_core.Divider, null), /*#__PURE__*/_react.default.createElement(_core.DialogContent, null, /*#__PURE__*/_react.default.createElement(_core.Typography, null, "Are you sure you want to return to the import form? This will lose your current view")), /*#__PURE__*/_react.default.createElement(_core.DialogActions, null, /*#__PURE__*/_react.default.createElement(_core.Button, {
45
+ onClick: function onClick() {
46
+ model.clearView();
47
+ handleClose();
48
+ },
49
+ variant: "contained",
50
+ color: "primary",
51
+ autoFocus: true
52
+ }, "OK"), /*#__PURE__*/_react.default.createElement(_core.Button, {
53
+ onClick: function onClick() {
54
+ return handleClose();
55
+ },
56
+ color: "secondary",
57
+ variant: "contained"
58
+ }, "Cancel")));
59
+ }
60
+
61
+ var _default = (0, _mobxReact.observer)(ReturnToImportFormDialog);
62
+
63
+ exports.default = _default;
package/ui/Tooltip.d.ts CHANGED
@@ -5,7 +5,7 @@ declare const _default: ({ offsetX, offsetY, configuration, feature, timeout, }:
5
5
  offsetY: number;
6
6
  configuration: import("mobx-state-tree").ModelInstanceTypeProps<Record<string, any>> & {
7
7
  setSubschema(slotName: string, data: unknown): any;
8
- } & import("mobx-state-tree").IStateTreeNode<import("../configuration/configurationSchema").AnyConfigurationSchemaType>;
8
+ } & import("mobx-state-tree").IStateTreeNode<import("../configuration").AnyConfigurationSchemaType>;
9
9
  feature?: Feature | undefined;
10
10
  timeout?: number | undefined;
11
11
  }) => JSX.Element | null;
package/ui/Tooltip.js CHANGED
@@ -13,7 +13,7 @@ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/sli
13
13
 
14
14
  var _react = _interopRequireWildcard(require("react"));
15
15
 
16
- var _styles = require("@material-ui/core/styles");
16
+ var _core = require("@material-ui/core");
17
17
 
18
18
  var _mobxReact = require("mobx-react");
19
19
 
@@ -23,7 +23,7 @@ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "functio
23
23
 
24
24
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
25
25
 
26
- var useStyles = (0, _styles.makeStyles)({
26
+ var useStyles = (0, _core.makeStyles)({
27
27
  hoverLabel: {
28
28
  border: '1px solid black',
29
29
  position: 'absolute',
package/ui/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  export * from './theme';
2
2
  export { LogoFull, Logomark } from './Logo';
3
3
  export { default as App } from './App';
4
+ export { default as ReturnToImportFormDialog } from './ReturnToImportFormDialog';
4
5
  export { default as ErrorMessage } from './ErrorMessage';
6
+ export { default as AssemblySelector } from './AssemblySelector';
5
7
  export { default as FileSelector } from './FileSelector';
6
8
  export { default as PrerenderedCanvas } from './PrerenderedCanvas';
7
9
  export { default as ResizeHandle } from './ResizeHandle';
package/ui/index.js CHANGED
@@ -11,7 +11,9 @@ var _exportNames = {
11
11
  LogoFull: true,
12
12
  Logomark: true,
13
13
  App: true,
14
+ ReturnToImportFormDialog: true,
14
15
  ErrorMessage: true,
16
+ AssemblySelector: true,
15
17
  FileSelector: true,
16
18
  PrerenderedCanvas: true,
17
19
  ResizeHandle: true,
@@ -28,6 +30,12 @@ Object.defineProperty(exports, "App", {
28
30
  return _App.default;
29
31
  }
30
32
  });
33
+ Object.defineProperty(exports, "AssemblySelector", {
34
+ enumerable: true,
35
+ get: function get() {
36
+ return _AssemblySelector.default;
37
+ }
38
+ });
31
39
  Object.defineProperty(exports, "EditableTypography", {
32
40
  enumerable: true,
33
41
  get: function get() {
@@ -88,6 +96,12 @@ Object.defineProperty(exports, "ResizeHandle", {
88
96
  return _ResizeHandle.default;
89
97
  }
90
98
  });
99
+ Object.defineProperty(exports, "ReturnToImportFormDialog", {
100
+ enumerable: true,
101
+ get: function get() {
102
+ return _ReturnToImportFormDialog.default;
103
+ }
104
+ });
91
105
  Object.defineProperty(exports, "SanitizedHTML", {
92
106
  enumerable: true,
93
107
  get: function get() {
@@ -119,8 +133,12 @@ var _Logo = require("./Logo");
119
133
 
120
134
  var _App = _interopRequireDefault(require("./App"));
121
135
 
136
+ var _ReturnToImportFormDialog = _interopRequireDefault(require("./ReturnToImportFormDialog"));
137
+
122
138
  var _ErrorMessage = _interopRequireDefault(require("./ErrorMessage"));
123
139
 
140
+ var _AssemblySelector = _interopRequireDefault(require("./AssemblySelector"));
141
+
124
142
  var _FileSelector = _interopRequireDefault(require("./FileSelector"));
125
143
 
126
144
  var _PrerenderedCanvas = _interopRequireDefault(require("./PrerenderedCanvas"));
package/ui/theme.d.ts CHANGED
@@ -115,6 +115,14 @@ export declare function createJBrowseDefaultOverrides(palette?: PaletteOptions):
115
115
  color: string;
116
116
  };
117
117
  };
118
+ MuiAccordion: {
119
+ root: {
120
+ margin: number;
121
+ '&$expanded': {
122
+ margin: number;
123
+ };
124
+ };
125
+ };
118
126
  MuiAccordionSummary: {
119
127
  root: {
120
128
  backgroundColor: string;
package/ui/theme.js CHANGED
@@ -137,6 +137,15 @@ function createJBrowseDefaultOverrides() {
137
137
  color: generatedPalette.tertiary.main
138
138
  }
139
139
  },
140
+ MuiAccordion: {
141
+ root: {
142
+ // avoid extra padding around accordion element
143
+ margin: 0,
144
+ '&$expanded': {
145
+ margin: 0
146
+ }
147
+ }
148
+ },
140
149
  MuiAccordionSummary: {
141
150
  root: {
142
151
  // !important needed to combat the MuiButton being applied to
package/ui/theme.test.js CHANGED
@@ -62,7 +62,7 @@ describe('theme utils', function () {
62
62
  }
63
63
  });
64
64
  expect((_theme$overrides = theme.overrides) === null || _theme$overrides === void 0 ? void 0 : _theme$overrides.MuiPaper).toEqual(muiPaperStyle);
65
- expect(Object.keys(theme.overrides || {}).length).toBe(9);
65
+ expect(Object.keys(theme.overrides || {}).length).toBe(10);
66
66
  });
67
67
  it('allows modifying a default override', function () {
68
68
  var _theme$overrides2;
@@ -78,7 +78,7 @@ describe('theme utils', function () {
78
78
  }
79
79
  });
80
80
  expect((_theme$overrides2 = theme.overrides) === null || _theme$overrides2 === void 0 ? void 0 : _theme$overrides2.MuiButton).toEqual(muiButtonStyle);
81
- expect(Object.keys(theme.overrides || {}).length).toBe(8);
81
+ expect(Object.keys(theme.overrides || {}).length).toBe(9);
82
82
  });
83
83
  it('allows adding a custom prop', function () {
84
84
  var _theme$props;
@@ -9,6 +9,7 @@ export interface BpOffset {
9
9
  end?: number;
10
10
  }
11
11
  declare const Base1DView: import("mobx-state-tree").IModelType<{
12
+ id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
12
13
  displayedRegions: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
13
14
  refName: import("mobx-state-tree").ISimpleType<string>;
14
15
  start: import("mobx-state-tree").ISimpleType<number>;
@@ -32,6 +33,7 @@ declare const Base1DView: import("mobx-state-tree").IModelType<{
32
33
  setVolatileWidth(width: number): void;
33
34
  } & {
34
35
  readonly width: number;
36
+ readonly assemblyNames: string[];
35
37
  readonly displayedRegionsTotalPx: number;
36
38
  readonly maxOffset: number;
37
39
  readonly minOffset: number;
@@ -9,6 +9,8 @@ exports.default = void 0;
9
9
 
10
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
11
 
12
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
13
+
12
14
  var _mobxStateTree = require("mobx-state-tree");
13
15
 
14
16
  var _index = require("./index");
@@ -24,6 +26,7 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
24
26
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { (0, _defineProperty2.default)(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
25
27
 
26
28
  var Base1DView = _mobxStateTree.types.model('Base1DView', {
29
+ id: _mst.ElementId,
27
30
  displayedRegions: _mobxStateTree.types.array(_mst.Region),
28
31
  bpPerPx: 0,
29
32
  offsetPx: 0,
@@ -52,6 +55,12 @@ var Base1DView = _mobxStateTree.types.model('Base1DView', {
52
55
  return self.volatileWidth;
53
56
  },
54
57
 
58
+ get assemblyNames() {
59
+ return (0, _toConsumableArray2.default)(new Set(self.displayedRegions.map(function (region) {
60
+ return region.assemblyName;
61
+ })));
62
+ },
63
+
55
64
  get displayedRegionsTotalPx() {
56
65
  return this.totalBp / self.bpPerPx;
57
66
  },
package/util/index.d.ts CHANGED
@@ -65,6 +65,7 @@ export interface ParsedLocString {
65
65
  refName: string;
66
66
  start?: number;
67
67
  end?: number;
68
+ reversed?: boolean;
68
69
  }
69
70
  export declare function parseLocStringOneBased(locString: string, isValidRefName: (refName: string, assemblyName?: string) => boolean): ParsedLocString;
70
71
  /**
@@ -307,7 +308,16 @@ export declare function generateCodonTable(table: any): {
307
308
  export declare function updateStatus<U>(msg: string, cb: (arg: string) => void, fn: () => U): Promise<U>;
308
309
  export declare function hashCode(str: string): number;
309
310
  export declare function objectHash(obj: Record<string, any>): string;
310
- export declare function bytesForRegions(regions: Region[], index: any): Promise<number>;
311
+ interface VirtualOffset {
312
+ blockPosition: number;
313
+ }
314
+ interface Block {
315
+ minv: VirtualOffset;
316
+ maxv: VirtualOffset;
317
+ }
318
+ export declare function bytesForRegions(regions: Region[], index: {
319
+ blocksForRange: (ref: string, start: number, end: number) => Promise<Block[]>;
320
+ }): Promise<number>;
311
321
  export declare type ViewSnap = {
312
322
  bpPerPx: number;
313
323
  interRegionPaddingWidth: number;
@@ -329,3 +339,4 @@ export declare function viewBpToPx({ refName, coord, regionNumber, self, }: {
329
339
  index: number;
330
340
  offsetPx: number;
331
341
  } | undefined;
342
+ export declare function getBpDisplayStr(totalBp: number): string;
package/util/index.js CHANGED
@@ -56,6 +56,7 @@ var _exportNames = {
56
56
  objectHash: true,
57
57
  bytesForRegions: true,
58
58
  viewBpToPx: true,
59
+ getBpDisplayStr: true,
59
60
  SimpleFeature: true,
60
61
  isFeature: true
61
62
  };
@@ -81,6 +82,7 @@ exports.findLastIndex = findLastIndex;
81
82
  exports.findParentThat = findParentThat;
82
83
  exports.findParentThatIs = findParentThatIs;
83
84
  exports.generateCodonTable = generateCodonTable;
85
+ exports.getBpDisplayStr = getBpDisplayStr;
84
86
  exports.getContainingDisplay = getContainingDisplay;
85
87
  exports.getContainingTrack = getContainingTrack;
86
88
  exports.getContainingView = getContainingView;
@@ -469,7 +471,8 @@ function assembleLocString(region) {
469
471
  var assemblyName = region.assemblyName,
470
472
  refName = region.refName,
471
473
  start = region.start,
472
- end = region.end;
474
+ end = region.end,
475
+ reversed = region.reversed;
473
476
  var assemblyNameString = assemblyName ? "{".concat(assemblyName, "}") : '';
474
477
  var startString;
475
478
 
@@ -489,17 +492,29 @@ function assembleLocString(region) {
489
492
  endString = start !== undefined ? '..' : '';
490
493
  }
491
494
 
492
- return "".concat(assemblyNameString).concat(refName).concat(startString).concat(endString);
495
+ var rev = '';
496
+
497
+ if (reversed) {
498
+ rev = '[rev]';
499
+ }
500
+
501
+ return "".concat(assemblyNameString).concat(refName).concat(startString).concat(endString).concat(rev);
493
502
  }
494
503
 
495
504
  function parseLocStringOneBased(locString, isValidRefName) {
496
505
  if (!locString) {
497
506
  throw new Error('no location string provided, could not parse');
507
+ }
508
+
509
+ var reversed = false;
510
+
511
+ if (locString.endsWith('[rev]')) {
512
+ reversed = true;
513
+ locString = locString.replace(/\[rev\]$/, '');
498
514
  } // remove any whitespace
499
515
 
500
516
 
501
- locString = locString.replace(/\s/, ''); // refNames can have colons :(
502
- // https://samtools.github.io/hts-specs/SAMv1.pdf Appendix A
517
+ locString = locString.replace(/\s/, ''); // refNames can have colons, ref https://samtools.github.io/hts-specs/SAMv1.pdf Appendix A
503
518
 
504
519
  var assemblyMatch = locString.match(/(\{(.+)\})?(.+)/);
505
520
 
@@ -521,7 +536,8 @@ function parseLocStringOneBased(locString, isValidRefName) {
521
536
  if (isValidRefName(location, assemblyName)) {
522
537
  return {
523
538
  assemblyName: assemblyName,
524
- refName: location
539
+ refName: location,
540
+ reversed: reversed
525
541
  };
526
542
  }
527
543
 
@@ -542,37 +558,40 @@ function parseLocStringOneBased(locString, isValidRefName) {
542
558
 
543
559
  if (rangeMatch) {
544
560
  var _rangeMatch = (0, _slicedToArray2.default)(rangeMatch, 6),
545
- start = _rangeMatch[1],
546
- end = _rangeMatch[5];
561
+ _start = _rangeMatch[1],
562
+ _end = _rangeMatch[5];
547
563
 
548
- if (start !== undefined && end !== undefined) {
564
+ if (_start !== undefined && _end !== undefined) {
549
565
  return {
550
566
  assemblyName: assemblyName,
551
567
  refName: prefix,
552
- start: +start.replace(/,/g, ''),
553
- end: +end.replace(/,/g, '')
568
+ start: +_start.replace(/,/g, ''),
569
+ end: +_end.replace(/,/g, ''),
570
+ reversed: reversed
554
571
  };
555
572
  }
556
573
  } else if (singleMatch) {
557
574
  var _singleMatch = (0, _slicedToArray2.default)(singleMatch, 5),
558
- _start = _singleMatch[1],
575
+ _start2 = _singleMatch[1],
559
576
  separator = _singleMatch[4];
560
577
 
561
- if (_start !== undefined) {
578
+ if (_start2 !== undefined) {
562
579
  if (separator) {
563
580
  // indefinite end
564
581
  return {
565
582
  assemblyName: assemblyName,
566
583
  refName: prefix,
567
- start: +_start.replace(/,/g, '')
584
+ start: +_start2.replace(/,/g, ''),
585
+ reversed: reversed
568
586
  };
569
587
  }
570
588
 
571
589
  return {
572
590
  assemblyName: assemblyName,
573
591
  refName: prefix,
574
- start: +_start.replace(/,/g, ''),
575
- end: +_start.replace(/,/g, '')
592
+ start: +_start2.replace(/,/g, ''),
593
+ end: +_start2.replace(/,/g, ''),
594
+ reversed: reversed
576
595
  };
577
596
  }
578
597
  } else {
@@ -581,13 +600,15 @@ function parseLocStringOneBased(locString, isValidRefName) {
581
600
  } else {
582
601
  return {
583
602
  assemblyName: assemblyName,
584
- refName: prefix
603
+ refName: prefix,
604
+ reversed: reversed
585
605
  };
586
606
  }
587
607
  } else if (isValidRefName(location, assemblyName)) {
588
608
  return {
589
609
  assemblyName: assemblyName,
590
- refName: location
610
+ refName: location,
611
+ reversed: reversed
591
612
  };
592
613
  }
593
614
 
@@ -1373,4 +1394,18 @@ function viewBpToPx(_ref3) {
1373
1394
  }
1374
1395
 
1375
1396
  return undefined;
1397
+ }
1398
+
1399
+ function getBpDisplayStr(totalBp) {
1400
+ var displayBp;
1401
+
1402
+ if (Math.floor(totalBp / 1000000) > 0) {
1403
+ displayBp = "".concat(parseFloat((totalBp / 1000000).toPrecision(3)), "Mbp");
1404
+ } else if (Math.floor(totalBp / 1000) > 0) {
1405
+ displayBp = "".concat(parseFloat((totalBp / 1000).toPrecision(3)), "Kbp");
1406
+ } else {
1407
+ displayBp = "".concat(Math.floor(totalBp), "bp");
1408
+ }
1409
+
1410
+ return displayBp;
1376
1411
  }
@@ -68,7 +68,8 @@ describe('parseLocString', function () {
68
68
  }], ['{hg19}chr1', {
69
69
  assemblyName: 'hg19',
70
70
  refName: 'chr1'
71
- }]];
71
+ }]]; // test unreversed
72
+
72
73
  cases.forEach(function (_ref) {
73
74
  var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
74
75
  input = _ref2[0],
@@ -76,8 +77,24 @@ describe('parseLocString', function () {
76
77
 
77
78
  test("".concat(input), function () {
78
79
  expect((0, _index.parseLocString)(input, function (refName) {
79
- return refName === 'chr1' || refName === 'chr2';
80
- })).toEqual(output);
80
+ return ['chr1', 'chr2'].includes(refName);
81
+ })).toEqual(_objectSpread(_objectSpread({}, output), {}, {
82
+ reversed: false
83
+ }));
84
+ });
85
+ }); // test reversed
86
+
87
+ cases.forEach(function (_ref3) {
88
+ var _ref4 = (0, _slicedToArray2.default)(_ref3, 2),
89
+ input = _ref4[0],
90
+ output = _ref4[1];
91
+
92
+ test("".concat(input), function () {
93
+ expect((0, _index.parseLocString)(input + '[rev]', function (refName) {
94
+ return ['chr1', 'chr2'].includes(refName);
95
+ })).toEqual(_objectSpread(_objectSpread({}, output), {}, {
96
+ reversed: true
97
+ }));
81
98
  });
82
99
  });
83
100
  });
@@ -117,10 +134,10 @@ describe('assembleLocString', function () {
117
134
  end: -1,
118
135
  refName: 'chr1'
119
136
  }, 'chr1:-99..-1']];
120
- cases.forEach(function (_ref3) {
121
- var _ref4 = (0, _slicedToArray2.default)(_ref3, 2),
122
- input = _ref4[0],
123
- output = _ref4[1];
137
+ cases.forEach(function (_ref5) {
138
+ var _ref6 = (0, _slicedToArray2.default)(_ref5, 2),
139
+ input = _ref6[0],
140
+ output = _ref6[1];
124
141
 
125
142
  test("assemble ".concat(output), function () {
126
143
  expect((0, _index.assembleLocString)(input)).toEqual(output);
@@ -128,7 +145,9 @@ describe('assembleLocString', function () {
128
145
  test("assemble and parse ".concat(output), function () {
129
146
  expect((0, _index.parseLocString)((0, _index.assembleLocString)(input), function (refName) {
130
147
  return refName === 'chr1' || refName === 'chr2';
131
- })).toEqual(input);
148
+ })).toEqual(_objectSpread(_objectSpread({}, input), {}, {
149
+ reversed: false
150
+ }));
132
151
  });
133
152
  }); // Special case since undefined `start` will result in `start` being assumed
134
153
  // to be `0`
@@ -152,17 +171,19 @@ describe('assembleLocString', function () {
152
171
  expect((0, _index.parseLocString)((0, _index.assembleLocString)(location), function (refName) {
153
172
  return refName === 'chr1' || refName === 'chr2';
154
173
  })).toEqual(_objectSpread(_objectSpread({}, location), {}, {
155
- start: 0
174
+ start: 0,
175
+ reversed: false,
176
+ assemblyName: undefined
156
177
  }));
157
178
  });
158
179
  });
159
180
  describe('compareLocStrings', function () {
160
181
  var cases = [['chr1:1..200', 'chr1:1-200', 0], ['chr1:1-200', '{hg19}chr1:1-200', -1], ['{hg19}chr1:1-200', 'chr1:1-200', 1], ['{hg19}chr1:1-200', '{hg19}chr1:2-200', -1]];
161
- cases.forEach(function (_ref5) {
162
- var _ref6 = (0, _slicedToArray2.default)(_ref5, 3),
163
- input1 = _ref6[0],
164
- input2 = _ref6[1],
165
- output = _ref6[2];
182
+ cases.forEach(function (_ref7) {
183
+ var _ref8 = (0, _slicedToArray2.default)(_ref7, 3),
184
+ input1 = _ref8[0],
185
+ input2 = _ref8[1],
186
+ output = _ref8[2];
166
187
 
167
188
  test("".concat(input1, " ").concat(input2, " = ").concat(output), function () {
168
189
  expect((0, _index.compareLocStrings)(input1, input2, function (refName) {