@jbrowse/core 2.3.4 → 2.4.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 (46) hide show
  1. package/BaseFeatureWidget/BaseFeatureDetail.d.ts +18 -19
  2. package/BaseFeatureWidget/BaseFeatureDetail.js +64 -61
  3. package/BaseFeatureWidget/SequenceBox.js +9 -3
  4. package/BaseFeatureWidget/SequenceFeatureDetails.js +70 -52
  5. package/BaseFeatureWidget/SequencePanel.d.ts +3 -3
  6. package/BaseFeatureWidget/SequencePanel.js +8 -5
  7. package/CorePlugin.js +2 -7
  8. package/PluginLoader.d.ts +1 -1
  9. package/PluginLoader.js +17 -21
  10. package/data_adapters/CytobandAdapter/CytobandAdapter.d.ts +8 -0
  11. package/data_adapters/CytobandAdapter/CytobandAdapter.js +40 -0
  12. package/data_adapters/CytobandAdapter/configSchema.d.ts +2 -0
  13. package/data_adapters/CytobandAdapter/configSchema.js +17 -0
  14. package/data_adapters/CytobandAdapter/index.d.ts +3 -0
  15. package/data_adapters/CytobandAdapter/index.js +37 -0
  16. package/package.json +5 -4
  17. package/pluggableElementTypes/PluggableElementBase.d.ts +1 -1
  18. package/pluggableElementTypes/PluggableElementBase.js +1 -2
  19. package/pluggableElementTypes/RpcMethodType.d.ts +5 -8
  20. package/pluggableElementTypes/RpcMethodType.js +22 -33
  21. package/pluggableElementTypes/renderers/CircularChordRendererType.d.ts +13 -2
  22. package/pluggableElementTypes/renderers/CircularChordRendererType.js +10 -2
  23. package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.d.ts +6 -0
  24. package/pluggableElementTypes/renderers/ComparativeServerSideRendererType.js +9 -1
  25. package/pluggableElementTypes/renderers/ServerSideRendererType.js +2 -34
  26. package/tsconfig.build.tsbuildinfo +1 -1
  27. package/ui/App.js +3 -18
  28. package/ui/LoadingEllipses.js +6 -6
  29. package/ui/Menu.js +2 -2
  30. package/ui/ResizeBar.js +4 -5
  31. package/ui/SanitizedHTML.js +2 -0
  32. package/ui/ViewContainer.js +3 -38
  33. package/ui/ViewMenu.d.ts +9 -0
  34. package/ui/ViewMenu.js +69 -0
  35. package/ui/ViewPanel.d.ts +19 -0
  36. package/ui/ViewPanel.js +49 -0
  37. package/ui/theme.d.ts +10 -166
  38. package/ui/theme.js +260 -48
  39. package/util/index.d.ts +3 -2
  40. package/util/index.js +11 -5
  41. package/util/map-obj.d.ts +3 -0
  42. package/util/map-obj.js +33 -0
  43. package/util/offscreenCanvasUtils.d.ts +18 -4
  44. package/util/offscreenCanvasUtils.js +48 -7
  45. package/data_adapters/CytobandAdapter.d.ts +0 -8
  46. package/data_adapters/CytobandAdapter.js +0 -49
package/PluginLoader.js CHANGED
@@ -5,6 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.isCJSPluginDefinition = exports.isESMPluginDefinition = exports.isUMDPluginDefinition = void 0;
7
7
  const load_script2_1 = __importDefault(require("load-script2"));
8
+ // locals
9
+ const Plugin_1 = __importDefault(require("./Plugin"));
8
10
  const ReExports_1 = __importDefault(require("./ReExports"));
9
11
  const util_1 = require("./util");
10
12
  function isUMDPluginDefinition(def) {
@@ -23,18 +25,8 @@ function isCJSPluginDefinition(def) {
23
25
  return def.cjsUrl !== undefined;
24
26
  }
25
27
  exports.isCJSPluginDefinition = isCJSPluginDefinition;
26
- function getGlobalObject() {
27
- // Based on window-or-global
28
- // https://github.com/purposeindustries/window-or-global/blob/322abc71de0010c9e5d9d0729df40959e1ef8775/lib/index.js
29
- return (
30
- // eslint-disable-next-line no-restricted-globals
31
- (typeof self === 'object' && self.self === self && self) ||
32
- (typeof global === 'object' && global.global === global && global) ||
33
- // @ts-ignore
34
- this);
35
- }
36
- function isInWebWorker(globalObject) {
37
- return Boolean('WorkerGlobalScope' in globalObject);
28
+ function isInWebWorker() {
29
+ return Boolean('WorkerGlobalScope' in globalThis);
38
30
  }
39
31
  class PluginLoader {
40
32
  constructor(defs = [], args) {
@@ -44,14 +36,13 @@ class PluginLoader {
44
36
  this.definitions = JSON.parse(JSON.stringify(defs));
45
37
  }
46
38
  async loadScript(scriptUrl) {
47
- const globalObject = getGlobalObject();
48
- if (!isInWebWorker(globalObject)) {
39
+ if (!isInWebWorker()) {
49
40
  return (0, load_script2_1.default)(scriptUrl);
50
41
  }
51
42
  // @ts-ignore
52
- if (globalObject === null || globalObject === void 0 ? void 0 : globalObject.importScripts) {
43
+ if (globalThis === null || globalThis === void 0 ? void 0 : globalThis.importScripts) {
53
44
  // @ts-ignore
54
- await globalObject.importScripts(scriptUrl);
45
+ await globalThis.importScripts(scriptUrl);
55
46
  return;
56
47
  }
57
48
  throw new Error('cannot figure out how to load external JS scripts in this environment');
@@ -91,14 +82,19 @@ class PluginLoader {
91
82
  if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
92
83
  throw new Error(`cannot load plugins using protocol "${parsedUrl.protocol}"`);
93
84
  }
94
- await this.loadScript(parsedUrl.href);
95
85
  const moduleName = def.name;
96
86
  const umdName = `JBrowsePlugin${moduleName}`;
97
- const globalObject = getGlobalObject();
98
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
99
- const plugin = globalObject[umdName];
87
+ if (typeof jest !== 'undefined') {
88
+ // @ts-ignore
89
+ globalThis[umdName] = { default: Plugin_1.default };
90
+ }
91
+ else {
92
+ await this.loadScript(parsedUrl.href);
93
+ }
94
+ // @ts-ignore
95
+ const plugin = globalThis[umdName];
100
96
  if (!plugin) {
101
- throw new Error(`Failed to load UMD bundle for ${moduleName}, ${globalObject.constructor.name}.${umdName} is undefined`);
97
+ throw new Error(`Failed to load UMD bundle for ${moduleName}, ${umdName} is undefined`);
102
98
  }
103
99
  return plugin;
104
100
  }
@@ -0,0 +1,8 @@
1
+ /// <reference types="node" />
2
+ import { SimpleFeature } from '../../util';
3
+ import { BaseAdapter } from '../BaseAdapter';
4
+ export declare function isGzip(buf: Buffer): boolean;
5
+ export default class CytobandAdapter extends BaseAdapter {
6
+ getData(): Promise<SimpleFeature[]>;
7
+ freeResources(): void;
8
+ }
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isGzip = void 0;
4
+ const bgzf_filehandle_1 = require("@gmod/bgzf-filehandle");
5
+ // locals
6
+ const util_1 = require("../../util");
7
+ const io_1 = require("../../util/io");
8
+ const BaseAdapter_1 = require("../BaseAdapter");
9
+ function isGzip(buf) {
10
+ return buf[0] === 31 && buf[1] === 139 && buf[2] === 8;
11
+ }
12
+ exports.isGzip = isGzip;
13
+ class CytobandAdapter extends BaseAdapter_1.BaseAdapter {
14
+ async getData() {
15
+ const pm = this.pluginManager;
16
+ const loc = this.getConf('cytobandLocation');
17
+ if (loc.uri === '' || loc.uri === '/path/to/cytoband.txt.gz') {
18
+ return [];
19
+ }
20
+ const buffer = (await (0, io_1.openLocation)(loc, pm).readFile());
21
+ const buf = isGzip(buffer) ? await (0, bgzf_filehandle_1.unzip)(buffer) : buffer;
22
+ const text = new TextDecoder('utf8', { fatal: true }).decode(buf);
23
+ return text
24
+ .split(/\n|\r\n|\r/)
25
+ .filter(f => !!f.trim())
26
+ .map((line, i) => {
27
+ const [refName, start, end, name, type] = line.split('\t');
28
+ return new util_1.SimpleFeature({
29
+ uniqueId: `${i}`,
30
+ refName,
31
+ start: +start,
32
+ end: +end,
33
+ name,
34
+ type,
35
+ });
36
+ });
37
+ }
38
+ freeResources( /* { region } */) { }
39
+ }
40
+ exports.default = CytobandAdapter;
@@ -0,0 +1,2 @@
1
+ declare const configSchema: import("../../configuration").AnyConfigurationSchemaType;
2
+ export default configSchema;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const configuration_1 = require("../../configuration");
4
+ /**
5
+ * #config CytobandAdapter
6
+ */
7
+ function x() { } // eslint-disable-line @typescript-eslint/no-unused-vars
8
+ const configSchema = (0, configuration_1.ConfigurationSchema)('CytobandAdapter', {
9
+ /**
10
+ * #slot
11
+ */
12
+ cytobandLocation: {
13
+ type: 'fileLocation',
14
+ defaultValue: { uri: '/path/to/cytoband.txt.gz' },
15
+ },
16
+ }, { explicitlyTyped: true });
17
+ exports.default = configSchema;
@@ -0,0 +1,3 @@
1
+ import PluginManager from '../../PluginManager';
2
+ declare const _default: (pluginManager: PluginManager) => void;
3
+ export default _default;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
28
+ Object.defineProperty(exports, "__esModule", { value: true });
29
+ const pluggableElementTypes_1 = require("../../pluggableElementTypes");
30
+ const configSchema_1 = __importDefault(require("./configSchema"));
31
+ exports.default = (pluginManager) => {
32
+ pluginManager.addAdapterType(() => new pluggableElementTypes_1.AdapterType({
33
+ name: 'CytobandAdapter',
34
+ configSchema: configSchema_1.default,
35
+ getAdapterClass: () => Promise.resolve().then(() => __importStar(require('./CytobandAdapter'))).then(f => f.default),
36
+ }));
37
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/core",
3
- "version": "2.3.4",
3
+ "version": "2.4.0",
4
4
  "description": "JBrowse 2 core libraries used by plugins",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -29,6 +29,7 @@
29
29
  },
30
30
  "dependencies": {
31
31
  "@babel/runtime": "^7.17.9",
32
+ "@gmod/bgzf-filehandle": "^1.4.3",
32
33
  "@mui/icons-material": "^5.0.1",
33
34
  "@types/clone": "^2.0.0",
34
35
  "abortable-promise-cache": "^1.5.0",
@@ -40,7 +41,7 @@
40
41
  "copy-to-clipboard": "^3.3.1",
41
42
  "deepmerge": "^4.2.2",
42
43
  "detect-node": "^2.1.0",
43
- "dompurify": "^2.3.4",
44
+ "dompurify": "^3.0.0",
44
45
  "escape-html": "^1.0.3",
45
46
  "fast-deep-equal": "^3.1.3",
46
47
  "generic-filehandle": "^3.0.0",
@@ -50,7 +51,7 @@
50
51
  "json-stable-stringify": "^1.0.1",
51
52
  "librpc-web-mod": "^1.1.5",
52
53
  "load-script2": "^2.0.5",
53
- "material-ui-popup-state": "^3.0.0",
54
+ "material-ui-popup-state": "^5.0.0",
54
55
  "rbush": "^3.0.1",
55
56
  "react-error-boundary": "^3.0.0",
56
57
  "react-use-measure": "^2.1.1",
@@ -74,5 +75,5 @@
74
75
  "access": "public",
75
76
  "directory": "dist"
76
77
  },
77
- "gitHead": "98ae48be91ee2371e1b2768a907b4997995e9915"
78
+ "gitHead": "78707a2bc3ba8489f26a590ef83f62ede945d048"
78
79
  }
@@ -2,7 +2,7 @@ export default abstract class PluggableElementBase {
2
2
  name: string;
3
3
  maybeDisplayName?: string;
4
4
  constructor(args: {
5
- name: string;
5
+ name?: string;
6
6
  displayName?: string;
7
7
  });
8
8
  get displayName(): string;
@@ -2,8 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  class PluggableElementBase {
4
4
  constructor(args) {
5
- this.name = '';
6
- this.name = args.name;
5
+ this.name = args.name || 'UNKNOWN';
7
6
  this.maybeDisplayName = args.displayName;
8
7
  }
9
8
  get displayName() {
@@ -5,20 +5,17 @@ import { RemoteAbortSignal } from '../rpc/remoteAbortSignals';
5
5
  export type RpcMethodConstructor = new (pm: PluginManager) => RpcMethodType;
6
6
  export default abstract class RpcMethodType extends PluggableElementBase {
7
7
  pluginManager: PluginManager;
8
- name: string;
9
8
  constructor(pluginManager: PluginManager);
10
9
  serializeArguments(args: {}, _rpcDriverClassName: string): Promise<{}>;
11
10
  serializeNewAuthArguments(loc: UriLocation): Promise<UriLocation>;
12
- deserializeArguments<SERIALIZED extends {
11
+ deserializeArguments<T extends {
13
12
  signal?: RemoteAbortSignal;
14
13
  blobMap?: Record<string, File>;
15
- }>(serializedArgs: SERIALIZED, _rpcDriverClassName: string): Promise<(SERIALIZED & {
16
- signal: AbortSignal;
17
- }) | (SERIALIZED & {
18
- signal: undefined;
19
- })>;
14
+ }>(serializedArgs: T, _rpcDriverClassName: string): Promise<T & {
15
+ signal: AbortSignal | undefined;
16
+ }>;
20
17
  abstract execute(serializedArgs: unknown, rpcDriverClassName: string): Promise<unknown>;
21
18
  serializeReturn(originalReturn: unknown, _args: unknown, _rpcDriverClassName: string): Promise<unknown>;
22
- deserializeReturn(serializedReturn: unknown, _args: unknown, _rpcDriverClassName: string): Promise<unknown>;
19
+ deserializeReturn(serializedReturn: unknown, _args: unknown, _rpcDriver: string): Promise<unknown>;
23
20
  private augmentLocationObjects;
24
21
  }
@@ -3,16 +3,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ const map_obj_1 = __importDefault(require("../util/map-obj"));
6
7
  const PluggableElementBase_1 = __importDefault(require("./PluggableElementBase"));
7
8
  const tracks_1 = require("../util/tracks");
8
- const mobx_state_tree_1 = require("mobx-state-tree");
9
9
  const types_1 = require("../util/types");
10
10
  const remoteAbortSignals_1 = require("../rpc/remoteAbortSignals");
11
11
  class RpcMethodType extends PluggableElementBase_1.default {
12
12
  constructor(pluginManager) {
13
- super({ name: '' });
13
+ super({});
14
14
  this.pluginManager = pluginManager;
15
- this.name = 'UNKNOWN';
16
15
  }
17
16
  async serializeArguments(args, _rpcDriverClassName) {
18
17
  const blobMap = (0, tracks_1.getBlobMap)();
@@ -25,7 +24,7 @@ class RpcMethodType extends PluggableElementBase_1.default {
25
24
  if (!(0, types_1.isAppRootModel)(rootModel) || loc.internetAccountPreAuthorization) {
26
25
  return loc;
27
26
  }
28
- const account = rootModel === null || rootModel === void 0 ? void 0 : rootModel.findAppropriateInternetAccount(loc);
27
+ const account = rootModel.findAppropriateInternetAccount(loc);
29
28
  if (account) {
30
29
  loc.internetAccountPreAuthorization =
31
30
  await account.getPreAuthorizationInformation(loc);
@@ -37,55 +36,45 @@ class RpcMethodType extends PluggableElementBase_1.default {
37
36
  (0, tracks_1.setBlobMap)(serializedArgs.blobMap);
38
37
  }
39
38
  const { signal } = serializedArgs;
40
- if (signal && (0, remoteAbortSignals_1.isRemoteAbortSignal)(signal)) {
41
- return { ...serializedArgs, signal: (0, remoteAbortSignals_1.deserializeAbortSignal)(signal) };
42
- }
43
- return { ...serializedArgs, signal: undefined };
39
+ return {
40
+ ...serializedArgs,
41
+ signal: (0, remoteAbortSignals_1.isRemoteAbortSignal)(signal)
42
+ ? (0, remoteAbortSignals_1.deserializeAbortSignal)(signal)
43
+ : undefined,
44
+ };
44
45
  }
45
46
  async serializeReturn(originalReturn, _args, _rpcDriverClassName) {
46
47
  return originalReturn;
47
48
  }
48
- async deserializeReturn(serializedReturn, _args, _rpcDriverClassName) {
49
+ async deserializeReturn(serializedReturn, _args, _rpcDriver) {
50
+ var _a;
49
51
  let r;
50
- const { rootModel } = this.pluginManager;
51
52
  try {
52
53
  r = await serializedReturn;
53
54
  }
54
55
  catch (error) {
55
56
  if ((0, types_1.isAuthNeededException)(error)) {
57
+ const retryAccount =
56
58
  // @ts-ignore
57
- const retryAccount = rootModel === null || rootModel === void 0 ? void 0 : rootModel.createEphemeralInternetAccount(`HTTPBasicInternetAccount-${new URL(error.url).origin}`, {}, error.url);
59
+ (_a = this.pluginManager.rootModel) === null || _a === void 0 ? void 0 : _a.createEphemeralInternetAccount(`HTTPBasicInternetAccount-${new URL(error.url).origin}`, {}, error.url);
58
60
  throw new types_1.RetryError('Retrying with created internet account', retryAccount.internetAccountId);
59
61
  }
60
62
  throw error;
61
63
  }
62
64
  return r;
63
65
  }
64
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
65
66
  async augmentLocationObjects(thing) {
66
- if ((0, mobx_state_tree_1.isStateTreeNode)(thing) && !(0, mobx_state_tree_1.isAlive)(thing)) {
67
- return thing;
68
- }
69
- if ((0, types_1.isUriLocation)(thing)) {
70
- await this.serializeNewAuthArguments(thing);
71
- }
72
- if (Array.isArray(thing)) {
73
- for (const val of thing) {
74
- await this.augmentLocationObjects(val);
75
- }
76
- }
77
- if (typeof thing === 'object' && thing !== null) {
78
- for (const value of Object.values(thing)) {
79
- if (Array.isArray(value)) {
80
- for (const val of value) {
81
- await this.augmentLocationObjects(val);
82
- }
83
- }
84
- else if (typeof value === 'object' && value !== null) {
85
- await this.augmentLocationObjects(value);
86
- }
67
+ const uris = [];
68
+ // using map-obj avoids cycles, seen in circular view svg export
69
+ (0, map_obj_1.default)(thing, val => {
70
+ if ((0, types_1.isUriLocation)(val)) {
71
+ uris.push(val);
87
72
  }
73
+ });
74
+ for (const uri of uris) {
75
+ await this.serializeNewAuthArguments(uri);
88
76
  }
77
+ return thing;
89
78
  }
90
79
  }
91
80
  exports.default = RpcMethodType;
@@ -1,6 +1,8 @@
1
- import { SimpleFeatureSerialized } from '../../util/simpleFeature';
1
+ /// <reference types="react" />
2
+ import { SimpleFeature, SimpleFeatureSerialized } from '../../util';
2
3
  import FeatureRenderer from './FeatureRendererType';
3
4
  export default class CircularChordRendererType extends FeatureRenderer {
5
+ supportsSVG: boolean;
4
6
  deserializeResultsInClient(res: {
5
7
  features: SimpleFeatureSerialized[];
6
8
  html: string;
@@ -8,5 +10,14 @@ export default class CircularChordRendererType extends FeatureRenderer {
8
10
  exportSVG?: {
9
11
  rasterizeLayers?: boolean;
10
12
  };
11
- }): any;
13
+ }): {
14
+ features: Map<string, SimpleFeature>;
15
+ blockKey: string;
16
+ html: string;
17
+ } | {
18
+ features: Map<string, SimpleFeature>;
19
+ blockKey: string;
20
+ reactElement: JSX.Element;
21
+ html: string;
22
+ };
12
23
  }
@@ -4,12 +4,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const react_1 = __importDefault(require("react"));
7
- const simpleFeature_1 = __importDefault(require("../../util/simpleFeature"));
7
+ const util_1 = require("../../util");
8
8
  const FeatureRendererType_1 = __importDefault(require("./FeatureRendererType"));
9
9
  const RpcRenderedSvgGroup_1 = __importDefault(require("./RpcRenderedSvgGroup"));
10
10
  class CircularChordRendererType extends FeatureRendererType_1.default {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.supportsSVG = true;
14
+ }
11
15
  deserializeResultsInClient(res, args) {
12
- const deserializedFeatures = new Map(res.features.map(f => simpleFeature_1.default.fromJSON(f)).map(f => [f.id(), f]));
16
+ const deserializedFeatures = new Map(res.features.map(f => util_1.SimpleFeature.fromJSON(f)).map(f => [f.id(), f]));
13
17
  // if we are rendering svg, we skip hydration
14
18
  if (args.exportSVG) {
15
19
  // only return the res if the renderer explicitly has
@@ -17,6 +21,8 @@ class CircularChordRendererType extends FeatureRendererType_1.default {
17
21
  // document
18
22
  return {
19
23
  ...res,
24
+ features: deserializedFeatures,
25
+ blockKey: 'circularChord',
20
26
  html: this.supportsSVG
21
27
  ? res.html
22
28
  : '<text y="12" fill="black">SVG export not supported for this track</text>',
@@ -25,6 +31,8 @@ class CircularChordRendererType extends FeatureRendererType_1.default {
25
31
  // hydrate res using ServerSideRenderedContent
26
32
  return {
27
33
  ...res,
34
+ features: deserializedFeatures,
35
+ blockKey: 'circularChord',
28
36
  reactElement: (react_1.default.createElement(RpcRenderedSvgGroup_1.default, { ...args, ...res, features: deserializedFeatures, RenderingComponent: this.ReactComponent })),
29
37
  };
30
38
  }
@@ -18,6 +18,12 @@ export type ResultsSerialized = ServerSideResultsSerialized;
18
18
  export interface ResultsDeserialized extends ServerSideResultsDeserialized {
19
19
  blockKey: string;
20
20
  }
21
+ export interface ResultsSerializedSvgExport extends ResultsSerialized {
22
+ canvasRecordedData: unknown;
23
+ width: number;
24
+ height: number;
25
+ reactElement: unknown;
26
+ }
21
27
  export default class ComparativeServerSideRenderer extends ServerSideRenderer {
22
28
  /**
23
29
  * directly modifies the render arguments to prepare
@@ -9,6 +9,9 @@ const ServerSideRendererType_1 = __importDefault(require("./ServerSideRendererTy
9
9
  const dataAdapterCache_1 = require("../../data_adapters/dataAdapterCache");
10
10
  const util_1 = require("../../util");
11
11
  const rxjs_1 = require("rxjs");
12
+ function isSvgExport(e) {
13
+ return 'canvasRecordedData' in e;
14
+ }
12
15
  class ComparativeServerSideRenderer extends ServerSideRendererType_1.default {
13
16
  /**
14
17
  * directly modifies the render arguments to prepare
@@ -43,7 +46,12 @@ class ComparativeServerSideRenderer extends ServerSideRendererType_1.default {
43
46
  * calls `render` with the RPC manager.
44
47
  */
45
48
  async renderInClient(rpcManager, args) {
46
- return rpcManager.call(args.sessionId, 'ComparativeRender', args);
49
+ const results = (await rpcManager.call(args.sessionId, 'ComparativeRender', args));
50
+ if (isSvgExport(results)) {
51
+ results.html = await (0, util_1.getSerializedSvg)(results);
52
+ delete results.reactElement;
53
+ }
54
+ return results;
47
55
  }
48
56
  /**
49
57
  * @param renderArgs -
@@ -1,34 +1,10 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
26
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
4
  };
28
5
  Object.defineProperty(exports, "__esModule", { value: true });
29
6
  const react_1 = __importDefault(require("react"));
30
7
  const styles_1 = require("@mui/material/styles");
31
- const canvas_sequencer_1 = require("canvas-sequencer");
32
8
  const server_1 = require("react-dom/server");
33
9
  const mobx_state_tree_1 = require("mobx-state-tree");
34
10
  // locals
@@ -79,7 +55,7 @@ class ServerSideRenderer extends RendererType_1.default {
79
55
  : '<text y="12" fill="black">SVG export not supported for this track</text>',
80
56
  };
81
57
  }
82
- // hydrate res using ServerSideRenderedContent
58
+ // get res using ServerSideRenderedContent
83
59
  return {
84
60
  ...res,
85
61
  reactElement: (react_1.default.createElement(ServerSideRenderedContent_1.default, { ...args, ...res, RenderingComponent: this.ReactComponent })),
@@ -124,15 +100,7 @@ class ServerSideRenderer extends RendererType_1.default {
124
100
  async renderInClient(rpcManager, args) {
125
101
  const results = (await rpcManager.call(args.sessionId, 'CoreRender', args));
126
102
  if (isSvgExport(results)) {
127
- const { width, height, canvasRecordedData } = results;
128
- const C2S = await Promise.resolve().then(() => __importStar(require('canvas2svg')));
129
- const ctx = new C2S.default(width, height);
130
- const seq = new canvas_sequencer_1.CanvasSequence(canvasRecordedData);
131
- seq.execute(ctx);
132
- const str = ctx.getSvg();
133
- // innerHTML strips the outer <svg> element from returned data, we add
134
- // our own <svg> element in the view's SVG export
135
- results.html = str.innerHTML;
103
+ results.html = await (0, util_1.getSerializedSvg)(results);
136
104
  delete results.reactElement;
137
105
  }
138
106
  return results;