igv 3.5.3 → 3.5.4
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.
- package/README.md +10 -10
- package/dist/igv.esm.js +220 -366
- package/dist/igv.esm.min.js +9 -9
- package/dist/igv.esm.min.js.map +1 -1
- package/dist/igv.js +220 -366
- package/dist/igv.min.js +9 -9
- package/dist/igv.min.js.map +1 -1
- package/package.json +2 -2
package/dist/igv.esm.js
CHANGED
|
@@ -386,12 +386,12 @@ function numberFormatter$1(rawNumber) {
|
|
|
386
386
|
decsep = '.';
|
|
387
387
|
|
|
388
388
|
return dec[0].split('').reverse().reduce(function (prev, now, i) {
|
|
389
|
-
return i % 3 === 0 ? prev + sep + now : prev + now
|
|
390
|
-
}).split('').reverse().join('') + (dec[1] ? decsep + dec[1] : '')
|
|
389
|
+
return i % 3 === 0 ? prev + sep + now : prev + now
|
|
390
|
+
}).split('').reverse().join('') + (dec[1] ? decsep + dec[1] : '')
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
const splitLines$3 = function (string) {
|
|
394
|
-
return string.split(/\n|\r\n|\r/g)
|
|
394
|
+
return string.split(/\n|\r\n|\r/g)
|
|
395
395
|
};
|
|
396
396
|
|
|
397
397
|
|
|
@@ -419,24 +419,24 @@ function splitStringRespectingQuotes(string, delim) {
|
|
|
419
419
|
}
|
|
420
420
|
}
|
|
421
421
|
}
|
|
422
|
-
return tokens
|
|
422
|
+
return tokens
|
|
423
423
|
}
|
|
424
424
|
|
|
425
425
|
function stripQuotes$2(str) {
|
|
426
|
-
if(str === undefined) {
|
|
427
|
-
return str
|
|
426
|
+
if (str === undefined) {
|
|
427
|
+
return str
|
|
428
428
|
}
|
|
429
|
-
if(str.startsWith("'") || str.startsWith('"')) {
|
|
429
|
+
if (str.startsWith("'") || str.startsWith('"')) {
|
|
430
430
|
str = str.substring(1);
|
|
431
431
|
}
|
|
432
432
|
if (str.endsWith("'") || str.endsWith('"')) {
|
|
433
433
|
str = str.substring(0, str.length - 1);
|
|
434
434
|
}
|
|
435
|
-
return str
|
|
435
|
+
return str
|
|
436
436
|
}
|
|
437
437
|
|
|
438
438
|
function capitalize(str) {
|
|
439
|
-
return str.length > 0 ? str.charAt(0).toUpperCase() + str.slice(1) : str
|
|
439
|
+
return str.length > 0 ? str.charAt(0).toUpperCase() + str.slice(1) : str
|
|
440
440
|
}
|
|
441
441
|
|
|
442
442
|
|
|
@@ -460,7 +460,7 @@ function parseLocusString$1(string) {
|
|
|
460
460
|
range.end = range.start + 1;
|
|
461
461
|
}
|
|
462
462
|
|
|
463
|
-
return range
|
|
463
|
+
return range
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
/**
|
|
@@ -469,7 +469,7 @@ function parseLocusString$1(string) {
|
|
|
469
469
|
* @param urlOrFile
|
|
470
470
|
*/
|
|
471
471
|
|
|
472
|
-
function getFilename$
|
|
472
|
+
function getFilename$1(urlOrFile) {
|
|
473
473
|
|
|
474
474
|
if (urlOrFile.name !== undefined) {
|
|
475
475
|
return urlOrFile.name
|
|
@@ -496,8 +496,8 @@ function getFilename$2(urlOrFile) {
|
|
|
496
496
|
* @param object
|
|
497
497
|
*/
|
|
498
498
|
function isFile(object) {
|
|
499
|
-
if(!object) {
|
|
500
|
-
return false
|
|
499
|
+
if (!object) {
|
|
500
|
+
return false
|
|
501
501
|
}
|
|
502
502
|
return typeof object !== 'function' &&
|
|
503
503
|
(object instanceof File ||
|
|
@@ -517,7 +517,7 @@ function download(filename, data) {
|
|
|
517
517
|
|
|
518
518
|
if (typeof process === 'object' && typeof window === 'undefined') {
|
|
519
519
|
global.atob = function (str) {
|
|
520
|
-
return Buffer.from(str, 'base64').toString('binary')
|
|
520
|
+
return Buffer.from(str, 'base64').toString('binary')
|
|
521
521
|
};
|
|
522
522
|
}
|
|
523
523
|
|
|
@@ -536,7 +536,7 @@ function parseUri(str) {
|
|
|
536
536
|
if ($1) uri[o.q.name][$1] = $2;
|
|
537
537
|
});
|
|
538
538
|
|
|
539
|
-
return uri
|
|
539
|
+
return uri
|
|
540
540
|
}
|
|
541
541
|
|
|
542
542
|
const options = {
|
|
@@ -559,7 +559,7 @@ const options = {
|
|
|
559
559
|
* @returns {Promise<*>}
|
|
560
560
|
*/
|
|
561
561
|
async function resolveURL(url) {
|
|
562
|
-
return (typeof url === 'function')
|
|
562
|
+
return (typeof url === 'function') ? url() : url
|
|
563
563
|
}
|
|
564
564
|
|
|
565
565
|
/*! pako 2.1.0 https://github.com/nodeca/pako @license (MIT AND Zlib) */
|
|
@@ -7421,7 +7421,7 @@ const FEXTRA$1 = 4; // gzip spec F.EXTRA flag
|
|
|
7421
7421
|
|
|
7422
7422
|
function isgzipped(data) {
|
|
7423
7423
|
const b = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
|
|
7424
|
-
return b[0] ===31 && b[1] === 139
|
|
7424
|
+
return b[0] === 31 && b[1] === 139
|
|
7425
7425
|
}
|
|
7426
7426
|
|
|
7427
7427
|
/**
|
|
@@ -7431,9 +7431,9 @@ function ungzip_blocks(data) {
|
|
|
7431
7431
|
const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
|
|
7432
7432
|
const b = ba[3] & FEXTRA$1;
|
|
7433
7433
|
if (b !== 0 && ba[12] === 66 && ba[13] === 67) {
|
|
7434
|
-
return unbgzf(ba.buffer)
|
|
7434
|
+
return unbgzf(ba.buffer)
|
|
7435
7435
|
} else {
|
|
7436
|
-
return ungzip_1$1(ba)
|
|
7436
|
+
return ungzip_1$1(ba)
|
|
7437
7437
|
}
|
|
7438
7438
|
}
|
|
7439
7439
|
|
|
@@ -7459,7 +7459,7 @@ function unbgzf(data, lim) {
|
|
|
7459
7459
|
const start = 12 + xlen + ptr; // Start of CDATA
|
|
7460
7460
|
const bytesLeft = data.byteLength - start;
|
|
7461
7461
|
const cDataSize = bsize - xlen - 19;
|
|
7462
|
-
if (bytesLeft < cDataSize || cDataSize <= 0) break
|
|
7462
|
+
if (bytesLeft < cDataSize || cDataSize <= 0) break
|
|
7463
7463
|
|
|
7464
7464
|
const a = new Uint8Array(data, start, cDataSize);
|
|
7465
7465
|
const unc = inflateRaw_1(a);
|
|
@@ -7472,13 +7472,13 @@ function unbgzf(data, lim) {
|
|
|
7472
7472
|
oBlockList.push(unc);
|
|
7473
7473
|
} catch (e) {
|
|
7474
7474
|
console.error(e);
|
|
7475
|
-
break
|
|
7475
|
+
break
|
|
7476
7476
|
}
|
|
7477
7477
|
}
|
|
7478
7478
|
|
|
7479
7479
|
// Concatenate decompressed blocks
|
|
7480
7480
|
if (oBlockList.length === 1) {
|
|
7481
|
-
return oBlockList[0]
|
|
7481
|
+
return oBlockList[0]
|
|
7482
7482
|
} else {
|
|
7483
7483
|
const out = new Uint8Array(totalSize);
|
|
7484
7484
|
let cursor = 0;
|
|
@@ -7487,14 +7487,14 @@ function unbgzf(data, lim) {
|
|
|
7487
7487
|
arrayCopy(b, 0, out, cursor, b.length);
|
|
7488
7488
|
cursor += b.length;
|
|
7489
7489
|
}
|
|
7490
|
-
return out
|
|
7490
|
+
return out
|
|
7491
7491
|
}
|
|
7492
7492
|
}
|
|
7493
7493
|
|
|
7494
7494
|
function bgzBlockSize$1(data) {
|
|
7495
7495
|
const ba = ArrayBuffer.isView(data) ? data : new Uint8Array(data);
|
|
7496
7496
|
const bsize = (ba[17] << 8 | ba[16]) + 1;
|
|
7497
|
-
return bsize
|
|
7497
|
+
return bsize
|
|
7498
7498
|
}
|
|
7499
7499
|
|
|
7500
7500
|
// From Thomas Down's zlib implementation
|
|
@@ -7504,12 +7504,12 @@ const hasSubarray = (typeof testArray.subarray === 'function');
|
|
|
7504
7504
|
|
|
7505
7505
|
function arrayCopy(src, srcOffset, dest, destOffset, count) {
|
|
7506
7506
|
if (count === 0) {
|
|
7507
|
-
return
|
|
7507
|
+
return
|
|
7508
7508
|
}
|
|
7509
7509
|
if (!src) {
|
|
7510
|
-
throw "Undef src"
|
|
7510
|
+
throw "Undef src"
|
|
7511
7511
|
} else if (!dest) {
|
|
7512
|
-
throw "Undef dest"
|
|
7512
|
+
throw "Undef dest"
|
|
7513
7513
|
}
|
|
7514
7514
|
if (srcOffset === 0 && count === src.length) {
|
|
7515
7515
|
arrayCopy_fast(src, dest, destOffset);
|
|
@@ -7546,7 +7546,7 @@ function compressString(str) {
|
|
|
7546
7546
|
const compressedBytes = new deflateRaw_1(bytes); // UInt8Arry
|
|
7547
7547
|
const compressedString = String.fromCharCode.apply(null, compressedBytes); // Convert to string
|
|
7548
7548
|
let enc = btoa(compressedString);
|
|
7549
|
-
return enc.replace(/\+/g, '.').replace(/\//g, '_').replace(/=/g, '-')
|
|
7549
|
+
return enc.replace(/\+/g, '.').replace(/\//g, '_').replace(/=/g, '-') // URL safe
|
|
7550
7550
|
}
|
|
7551
7551
|
|
|
7552
7552
|
/**
|
|
@@ -7571,7 +7571,7 @@ function uncompressString(enc) {
|
|
|
7571
7571
|
for (let b of bytes) {
|
|
7572
7572
|
str += String.fromCharCode(b);
|
|
7573
7573
|
}
|
|
7574
|
-
return str
|
|
7574
|
+
return str
|
|
7575
7575
|
}
|
|
7576
7576
|
|
|
7577
7577
|
|
|
@@ -7601,7 +7601,7 @@ function decodeDataURI$1(dataURI, gzip) {
|
|
|
7601
7601
|
}
|
|
7602
7602
|
return plain
|
|
7603
7603
|
} else {
|
|
7604
|
-
return decodeURIComponent(dataString)
|
|
7604
|
+
return decodeURIComponent(dataString) // URL encoded string -- not currently used or tested
|
|
7605
7605
|
}
|
|
7606
7606
|
}
|
|
7607
7607
|
|
|
@@ -7633,7 +7633,7 @@ function decodeDataURI$1(dataURI, gzip) {
|
|
|
7633
7633
|
const IGVMath = {
|
|
7634
7634
|
|
|
7635
7635
|
lerp: (v0, v1, t) => {
|
|
7636
|
-
return (1 - t) * v0 + t * v1
|
|
7636
|
+
return (1 - t) * v0 + t * v1
|
|
7637
7637
|
},
|
|
7638
7638
|
|
|
7639
7639
|
mean: function (array) {
|
|
@@ -7646,7 +7646,7 @@ const IGVMath = {
|
|
|
7646
7646
|
n++;
|
|
7647
7647
|
}
|
|
7648
7648
|
}
|
|
7649
|
-
return n > 0 ? t / n : 0
|
|
7649
|
+
return n > 0 ? t / n : 0
|
|
7650
7650
|
},
|
|
7651
7651
|
|
|
7652
7652
|
meanAndStdev: function (array) {
|
|
@@ -7663,7 +7663,7 @@ const IGVMath = {
|
|
|
7663
7663
|
n++;
|
|
7664
7664
|
}
|
|
7665
7665
|
}
|
|
7666
|
-
return n > 0 ? {mean: t / n, stdev: Math.sqrt(t2 - t * t / n)} : {mean: 0, stdev: 0}
|
|
7666
|
+
return n > 0 ? {mean: t / n, stdev: Math.sqrt(t2 - t * t / n)} : {mean: 0, stdev: 0}
|
|
7667
7667
|
},
|
|
7668
7668
|
|
|
7669
7669
|
median: function (numbers) {
|
|
@@ -7681,33 +7681,33 @@ const IGVMath = {
|
|
|
7681
7681
|
median = numbers[(numsLen - 1) / 2];
|
|
7682
7682
|
}
|
|
7683
7683
|
|
|
7684
|
-
return median
|
|
7684
|
+
return median
|
|
7685
7685
|
},
|
|
7686
7686
|
|
|
7687
7687
|
// Fast percentile function for "p" near edges. This needs profiled for p in middle (e.g. median)
|
|
7688
7688
|
percentile: function (array, p) {
|
|
7689
7689
|
|
|
7690
|
-
if (array.length === 0) return undefined
|
|
7690
|
+
if (array.length === 0) return undefined
|
|
7691
7691
|
|
|
7692
7692
|
var k = Math.floor(array.length * ((100 - p) / 100));
|
|
7693
7693
|
if (k === 0) {
|
|
7694
7694
|
array.sort(function (a, b) {
|
|
7695
7695
|
return b - a
|
|
7696
7696
|
});
|
|
7697
|
-
return array[k]
|
|
7697
|
+
return array[k]
|
|
7698
7698
|
} else {
|
|
7699
|
-
return selectElement(array, k)
|
|
7699
|
+
return selectElement(array, k)
|
|
7700
7700
|
}
|
|
7701
7701
|
|
|
7702
7702
|
},
|
|
7703
7703
|
|
|
7704
7704
|
|
|
7705
7705
|
clamp: function (value, min, max) {
|
|
7706
|
-
return Math.min(Math.max(value, min), max)
|
|
7706
|
+
return Math.min(Math.max(value, min), max)
|
|
7707
7707
|
},
|
|
7708
7708
|
|
|
7709
7709
|
log2: function (x) {
|
|
7710
|
-
return Math.log(x) / Math.LN2
|
|
7710
|
+
return Math.log(x) / Math.LN2
|
|
7711
7711
|
}
|
|
7712
7712
|
|
|
7713
7713
|
};
|
|
@@ -7733,7 +7733,7 @@ function selectElement(array, k) {
|
|
|
7733
7733
|
}
|
|
7734
7734
|
}
|
|
7735
7735
|
|
|
7736
|
-
return heap.content[0]
|
|
7736
|
+
return heap.content[0]
|
|
7737
7737
|
}
|
|
7738
7738
|
|
|
7739
7739
|
|
|
@@ -7760,7 +7760,7 @@ BinaryHeap.prototype = {
|
|
|
7760
7760
|
this.content[0] = end;
|
|
7761
7761
|
this.sinkDown(0);
|
|
7762
7762
|
}
|
|
7763
|
-
return result
|
|
7763
|
+
return result
|
|
7764
7764
|
},
|
|
7765
7765
|
|
|
7766
7766
|
remove: function (node) {
|
|
@@ -7768,24 +7768,24 @@ BinaryHeap.prototype = {
|
|
|
7768
7768
|
// To remove a value, we must search through the array to find
|
|
7769
7769
|
// it.
|
|
7770
7770
|
for (var i = 0; i < length; i++) {
|
|
7771
|
-
if (this.content[i] !== node) continue
|
|
7771
|
+
if (this.content[i] !== node) continue
|
|
7772
7772
|
// When it is found, the process seen in 'pop' is repeated
|
|
7773
7773
|
// to fill up the hole.
|
|
7774
7774
|
var end = this.content.pop();
|
|
7775
7775
|
// If the element we popped was the one we needed to remove,
|
|
7776
7776
|
// we're done.
|
|
7777
|
-
if (i === length - 1) break
|
|
7777
|
+
if (i === length - 1) break
|
|
7778
7778
|
// Otherwise, we replace the removed element with the popped
|
|
7779
7779
|
// one, and allow it to float up or sink down as appropriate.
|
|
7780
7780
|
this.content[i] = end;
|
|
7781
7781
|
this.bubbleUp(i);
|
|
7782
7782
|
this.sinkDown(i);
|
|
7783
|
-
break
|
|
7783
|
+
break
|
|
7784
7784
|
}
|
|
7785
7785
|
},
|
|
7786
7786
|
|
|
7787
7787
|
size: function () {
|
|
7788
|
-
return this.content.length
|
|
7788
|
+
return this.content.length
|
|
7789
7789
|
},
|
|
7790
7790
|
|
|
7791
7791
|
bubbleUp: function (n) {
|
|
@@ -7799,7 +7799,7 @@ BinaryHeap.prototype = {
|
|
|
7799
7799
|
// If the parent has a lesser score, things are in order and we
|
|
7800
7800
|
// are done.
|
|
7801
7801
|
if (score >= parent)
|
|
7802
|
-
break
|
|
7802
|
+
break
|
|
7803
7803
|
|
|
7804
7804
|
// Otherwise, swap the parent with the current element and
|
|
7805
7805
|
// continue.
|
|
@@ -7839,7 +7839,7 @@ BinaryHeap.prototype = {
|
|
|
7839
7839
|
}
|
|
7840
7840
|
|
|
7841
7841
|
// No need to swap further, we are done.
|
|
7842
|
-
if (swap == null) break
|
|
7842
|
+
if (swap == null) break
|
|
7843
7843
|
|
|
7844
7844
|
// Otherwise, swap and continue.
|
|
7845
7845
|
this.content[n] = this.content[swap];
|
|
@@ -8433,145 +8433,78 @@ function regExpEscape(s) {
|
|
|
8433
8433
|
}
|
|
8434
8434
|
|
|
8435
8435
|
function isGoogleURL(url) {
|
|
8436
|
-
|
|
8437
|
-
|
|
8438
|
-
|
|
8439
|
-
}
|
|
8440
|
-
|
|
8441
|
-
function isGoogleStorageURL(url) {
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
}
|
|
8447
|
-
|
|
8448
|
-
function isGoogleDriveURL(url) {
|
|
8449
|
-
|
|
8450
|
-
}
|
|
8451
|
-
|
|
8452
|
-
/**
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
function translateGoogleCloudURL(gsUrl) {
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
const qIdx = gsUrl.indexOf('?');
|
|
8464
|
-
const paramString = (qIdx > 0) ? gsUrl.substring(qIdx) + "&alt=media" : "?alt=media";
|
|
8465
|
-
|
|
8466
|
-
return `https://storage.googleapis.com/storage/v1/b/${bucket}/o/${object}${paramString}`
|
|
8467
|
-
}
|
|
8468
|
-
|
|
8469
|
-
/**
|
|
8470
|
-
* Parse a google bucket and object name from a google storage URL. Known forms include
|
|
8471
|
-
*
|
|
8472
|
-
* gs://BUCKET_NAME/OBJECT_NAME
|
|
8473
|
-
* https://storage.googleapis.com/BUCKET_NAME/OBJECT_NAME
|
|
8474
|
-
* https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME
|
|
8475
|
-
* https://www.googleapis.com/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME"
|
|
8476
|
-
* https://storage.googleapis.com/download/storage/v1/b/BUCKET_NAME/o/OBJECT_NAME
|
|
8477
|
-
*
|
|
8478
|
-
* @param url
|
|
8479
|
-
*/
|
|
8480
|
-
function parseBucketName(url) {
|
|
8481
|
-
|
|
8482
|
-
let bucket;
|
|
8483
|
-
let object;
|
|
8484
|
-
|
|
8485
|
-
if (url.startsWith("gs://")) {
|
|
8486
|
-
const i = url.indexOf('/', 5);
|
|
8487
|
-
if (i >= 0) {
|
|
8488
|
-
bucket = url.substring(5, i);
|
|
8489
|
-
const qIdx = url.indexOf('?');
|
|
8490
|
-
object = (qIdx < 0) ? url.substring(i + 1) : url.substring(i + 1, qIdx);
|
|
8491
|
-
}
|
|
8492
|
-
|
|
8493
|
-
} else if (url.startsWith("https://storage.googleapis.com") || url.startsWith("https://storage.cloud.google.com")) {
|
|
8494
|
-
const bucketIdx = url.indexOf("/v1/b/", 8);
|
|
8495
|
-
if (bucketIdx > 0) {
|
|
8496
|
-
const objIdx = url.indexOf("/o/", bucketIdx);
|
|
8497
|
-
if (objIdx > 0) {
|
|
8498
|
-
const queryIdx = url.indexOf("?", objIdx);
|
|
8499
|
-
bucket = url.substring(bucketIdx + 6, objIdx);
|
|
8500
|
-
object = queryIdx > 0 ? url.substring(objIdx + 3, queryIdx) : url.substring(objIdx + 3);
|
|
8501
|
-
}
|
|
8502
|
-
|
|
8503
|
-
} else {
|
|
8504
|
-
const idx1 = url.indexOf("/", 8);
|
|
8505
|
-
const idx2 = url.indexOf("/", idx1+1);
|
|
8506
|
-
const idx3 = url.indexOf("?", idx2);
|
|
8507
|
-
if (idx2 > 0) {
|
|
8508
|
-
bucket = url.substring(idx1+1, idx2);
|
|
8509
|
-
object = idx3 < 0 ? url.substring(idx2+1) : url.substring(idx2+1, idx3);
|
|
8510
|
-
}
|
|
8511
|
-
}
|
|
8436
|
+
return (url.includes("googleapis") && !url.includes("urlshortener")) ||
|
|
8437
|
+
isGoogleStorageURL(url) ||
|
|
8438
|
+
isGoogleDriveURL(url);
|
|
8439
|
+
}
|
|
8440
|
+
|
|
8441
|
+
function isGoogleStorageURL(url) {
|
|
8442
|
+
return url.startsWith("gs://") ||
|
|
8443
|
+
url.startsWith("https://www.googleapis.com/storage") ||
|
|
8444
|
+
url.startsWith("https://storage.cloud.google.com") ||
|
|
8445
|
+
url.startsWith("https://storage.googleapis.com");
|
|
8446
|
+
}
|
|
8447
|
+
|
|
8448
|
+
function isGoogleDriveURL(url) {
|
|
8449
|
+
return url.startsWith("https://www.googleapis.com/drive/v3/files");
|
|
8450
|
+
}
|
|
8451
|
+
|
|
8452
|
+
/**
|
|
8453
|
+
* Translate gs:// urls to https
|
|
8454
|
+
* See https://cloud.google.com/storage/docs/json_api/v1
|
|
8455
|
+
* @param gsUrl
|
|
8456
|
+
* @returns {string|*}
|
|
8457
|
+
*/
|
|
8458
|
+
function translateGoogleCloudURL(gsUrl) {
|
|
8459
|
+
try {
|
|
8460
|
+
let {bucket, object} = parseBucketName(gsUrl);
|
|
8461
|
+
object = encode(object);
|
|
8512
8462
|
|
|
8513
|
-
|
|
8514
|
-
|
|
8515
|
-
const objIdx = url.indexOf("/o/", bucketIdx);
|
|
8516
|
-
if (objIdx > 0) {
|
|
8517
|
-
const queryIdx = url.indexOf("?", objIdx);
|
|
8518
|
-
bucket = url.substring(bucketIdx + 6, objIdx);
|
|
8519
|
-
object = queryIdx > 0 ? url.substring(objIdx + 3, queryIdx) : url.substring(objIdx + 3);
|
|
8520
|
-
}
|
|
8521
|
-
}
|
|
8463
|
+
const qIdx = gsUrl.indexOf('?');
|
|
8464
|
+
let paramString = (qIdx > 0) ? gsUrl.substring(qIdx) : "";
|
|
8522
8465
|
|
|
8523
|
-
|
|
8524
|
-
|
|
8525
|
-
|
|
8526
|
-
}
|
|
8527
|
-
} else {
|
|
8528
|
-
throw Error(`Unrecognized Google Storage URI: ${url}`)
|
|
8529
|
-
}
|
|
8466
|
+
if (!paramString.includes("alt=media")) {
|
|
8467
|
+
paramString = paramString ? `${paramString}&alt=media` : "?alt=media";
|
|
8468
|
+
}
|
|
8530
8469
|
|
|
8531
|
-
}
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
* !, #, $, &, ', (, ), *, +, ,, /, :, ;, =, ?, @, [, ], and space characters.
|
|
8537
|
-
* @param obj
|
|
8538
|
-
*/
|
|
8470
|
+
return `https://storage.googleapis.com/storage/v1/b/${bucket}/o/${object}${paramString}`;
|
|
8471
|
+
} catch (error) {
|
|
8472
|
+
throw new Error(`Failed to translate Google Cloud URL: ${error.message}`);
|
|
8473
|
+
}
|
|
8474
|
+
}
|
|
8539
8475
|
|
|
8540
|
-
|
|
8476
|
+
/**
|
|
8477
|
+
* Parse a google bucket and object name from a google storage URL.
|
|
8478
|
+
* @param url
|
|
8479
|
+
*/
|
|
8480
|
+
function parseBucketName(url) {
|
|
8481
|
+
const regex = /gs:\/\/([a-zA-Z0-9._-]+)\/([^?]+)|https?:\/\/(?:storage\.googleapis\.com|storage\.cloud\.google\.com|www\.googleapis\.com)\/(?:storage\/v1\/b\/)?([a-zA-Z0-9._-]+)\/(?:o\/)?([^?]+)/;
|
|
8482
|
+
const match = url.match(regex);
|
|
8483
|
+
|
|
8484
|
+
if (match) {
|
|
8485
|
+
const bucket = match[1] || match[3];
|
|
8486
|
+
const object = match[2] || match[4];
|
|
8487
|
+
if (bucket && object) {
|
|
8488
|
+
return { bucket, object };
|
|
8489
|
+
}
|
|
8490
|
+
}
|
|
8491
|
+
throw new Error(`Unrecognized Google Storage URI: ${url}`);
|
|
8492
|
+
}
|
|
8541
8493
|
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
});
|
|
8550
|
-
return result;
|
|
8551
|
-
}
|
|
8494
|
+
/**
|
|
8495
|
+
* Percent a GCS object name. See https://cloud.google.com/storage/docs/request-endpoints
|
|
8496
|
+
* @param objectName
|
|
8497
|
+
*/
|
|
8498
|
+
function encode(objectName) {
|
|
8499
|
+
return objectName.split('').map(letter => encodings$1.get(letter) || letter).join('');
|
|
8500
|
+
}
|
|
8552
8501
|
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
encodings$1.set("&", "%26");
|
|
8560
|
-
encodings$1.set("'", "%27");
|
|
8561
|
-
encodings$1.set("(", "%28");
|
|
8562
|
-
encodings$1.set(")", "%29");
|
|
8563
|
-
encodings$1.set("*", "%2A");
|
|
8564
|
-
encodings$1.set("+", "%2B");
|
|
8565
|
-
encodings$1.set(",", "%2C");
|
|
8566
|
-
encodings$1.set("/", "%2F");
|
|
8567
|
-
encodings$1.set(":", "%3A");
|
|
8568
|
-
encodings$1.set(";", "%3B");
|
|
8569
|
-
encodings$1.set("=", "%3D");
|
|
8570
|
-
encodings$1.set("?", "%3F");
|
|
8571
|
-
encodings$1.set("@", "%40");
|
|
8572
|
-
encodings$1.set("[", "%5B");
|
|
8573
|
-
encodings$1.set("]", "%5D");
|
|
8574
|
-
encodings$1.set(" ", "%20");
|
|
8502
|
+
const encodings$1 = new Map([
|
|
8503
|
+
["!", "%21"], ["#", "%23"], ["$", "%24"], ["%", "%25"], ["&", "%26"],
|
|
8504
|
+
["'", "%27"], ["(", "%28"], [")", "%29"], ["*", "%2A"], ["+", "%2B"],
|
|
8505
|
+
[",", "%2C"], ["/", "%2F"], [":", "%3A"], [";", "%3B"], ["=", "%3D"],
|
|
8506
|
+
["?", "%3F"], ["@", "%40"], ["[", "%5B"], ["]", "%5D"], [" ", "%20"]
|
|
8507
|
+
]);
|
|
8575
8508
|
|
|
8576
8509
|
// Convenience functions for the gapi oAuth library.
|
|
8577
8510
|
|
|
@@ -8602,7 +8535,8 @@ async function init(config) {
|
|
|
8602
8535
|
// Attach an object to keep igv state
|
|
8603
8536
|
google.igv = {
|
|
8604
8537
|
tokenClient: tokenClient,
|
|
8605
|
-
apiKey: config.apiKey
|
|
8538
|
+
apiKey: config.apiKey,
|
|
8539
|
+
appId: config.appId
|
|
8606
8540
|
};
|
|
8607
8541
|
}
|
|
8608
8542
|
|
|
@@ -8622,8 +8556,6 @@ function getCurrentAccessToken() {
|
|
|
8622
8556
|
undefined
|
|
8623
8557
|
}
|
|
8624
8558
|
|
|
8625
|
-
|
|
8626
|
-
let promise;
|
|
8627
8559
|
/**
|
|
8628
8560
|
* Return a promise for an access token for the given scope. If the user hasn't authorized the scope request it
|
|
8629
8561
|
*
|
|
@@ -8642,27 +8574,21 @@ async function getAccessToken(scope) {
|
|
|
8642
8574
|
return google.igv.tokenResponse.access_token
|
|
8643
8575
|
} else {
|
|
8644
8576
|
const tokenClient = google.igv.tokenClient;
|
|
8645
|
-
|
|
8646
|
-
|
|
8647
|
-
|
|
8648
|
-
|
|
8649
|
-
|
|
8650
|
-
|
|
8651
|
-
|
|
8652
|
-
|
|
8653
|
-
|
|
8654
|
-
|
|
8655
|
-
|
|
8656
|
-
|
|
8657
|
-
|
|
8658
|
-
|
|
8659
|
-
|
|
8660
|
-
} catch (err) {
|
|
8661
|
-
console.log(err);
|
|
8662
|
-
}
|
|
8663
|
-
});
|
|
8664
|
-
}
|
|
8665
|
-
return promise
|
|
8577
|
+
return new Promise((resolve, reject) => {
|
|
8578
|
+
tokenClient.callback = (tokenResponse) => {
|
|
8579
|
+
if (tokenResponse.error !== undefined) {
|
|
8580
|
+
return reject(tokenResponse)
|
|
8581
|
+
}
|
|
8582
|
+
google.igv.tokenResponse = tokenResponse;
|
|
8583
|
+
google.igv.tokenExpiresAt = Date.now() + tokenResponse.expires_in * 1000;
|
|
8584
|
+
resolve(tokenResponse.access_token);
|
|
8585
|
+
};
|
|
8586
|
+
try {
|
|
8587
|
+
tokenClient.requestAccessToken({scope});
|
|
8588
|
+
} catch (err) {
|
|
8589
|
+
reject(err);
|
|
8590
|
+
}
|
|
8591
|
+
})
|
|
8666
8592
|
}
|
|
8667
8593
|
}
|
|
8668
8594
|
|
|
@@ -8681,90 +8607,6 @@ function getScopeForURL(url) {
|
|
|
8681
8607
|
}
|
|
8682
8608
|
}
|
|
8683
8609
|
|
|
8684
|
-
function getApiKey() {
|
|
8685
|
-
return google.igv.apiKey
|
|
8686
|
-
}
|
|
8687
|
-
|
|
8688
|
-
/**
|
|
8689
|
-
* Return information about a specific google drive URL
|
|
8690
|
-
*
|
|
8691
|
-
* @param googleDriveURL
|
|
8692
|
-
* @returns {Promise<any>}
|
|
8693
|
-
*/
|
|
8694
|
-
async function getDriveFileInfo(googleDriveURL) {
|
|
8695
|
-
|
|
8696
|
-
const id = getGoogleDriveFileID(googleDriveURL);
|
|
8697
|
-
let endPoint = "https://www.googleapis.com/drive/v3/files/" + id + "?supportsTeamDrives=true";
|
|
8698
|
-
const apiKey = getApiKey();
|
|
8699
|
-
if (apiKey) {
|
|
8700
|
-
endPoint += "&key=" + apiKey;
|
|
8701
|
-
}
|
|
8702
|
-
const response = await fetch(endPoint);
|
|
8703
|
-
let json = await response.json();
|
|
8704
|
-
if (json.error && json.error.code === 404) {
|
|
8705
|
-
let scope = "https://www.googleapis.com/auth/drive.file";
|
|
8706
|
-
const access_token = await getAccessToken(scope);
|
|
8707
|
-
if (access_token) {
|
|
8708
|
-
const response = await fetch(endPoint, {
|
|
8709
|
-
headers: {
|
|
8710
|
-
'Authorization': `Bearer ${access_token}`
|
|
8711
|
-
}
|
|
8712
|
-
});
|
|
8713
|
-
json = await response.json();
|
|
8714
|
-
if (json.error) {
|
|
8715
|
-
throw Error(json.error);
|
|
8716
|
-
}
|
|
8717
|
-
} else {
|
|
8718
|
-
throw Error(json.error);
|
|
8719
|
-
}
|
|
8720
|
-
}
|
|
8721
|
-
return json;
|
|
8722
|
-
}
|
|
8723
|
-
|
|
8724
|
-
|
|
8725
|
-
function getDriveDownloadURL(link) {
|
|
8726
|
-
// Return a google drive download url for the sharable link
|
|
8727
|
-
//https://drive.google.com/open?id=0B-lleX9c2pZFbDJ4VVRxakJzVGM
|
|
8728
|
-
//https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing
|
|
8729
|
-
var id = getGoogleDriveFileID(link);
|
|
8730
|
-
return id ? "https://www.googleapis.com/drive/v3/files/" + id + "?alt=media&supportsTeamDrives=true" : link;
|
|
8731
|
-
}
|
|
8732
|
-
|
|
8733
|
-
function getGoogleDriveFileID(link) {
|
|
8734
|
-
|
|
8735
|
-
//https://drive.google.com/file/d/1_FC4kCeO8E3V4dJ1yIW7A0sn1yURKIX-/view?usp=sharing
|
|
8736
|
-
//https://www.googleapis.com/drive/v3/files/1w-tvo6p1SH4p1OaQSVxpkV_EJgGIstWF?alt=media&supportsTeamDrives=true"
|
|
8737
|
-
|
|
8738
|
-
if (link.includes("/open?id=")) {
|
|
8739
|
-
const i1 = link.indexOf("/open?id=") + 9;
|
|
8740
|
-
const i2 = link.indexOf("&");
|
|
8741
|
-
if (i1 > 0 && i2 > i1) {
|
|
8742
|
-
return link.substring(i1, i2)
|
|
8743
|
-
} else if (i1 > 0) {
|
|
8744
|
-
return link.substring(i1);
|
|
8745
|
-
}
|
|
8746
|
-
|
|
8747
|
-
} else if (link.includes("/file/d/")) {
|
|
8748
|
-
const i1 = link.indexOf("/file/d/") + 8;
|
|
8749
|
-
const i2 = link.lastIndexOf("/");
|
|
8750
|
-
return link.substring(i1, i2);
|
|
8751
|
-
|
|
8752
|
-
} else if (link.startsWith("https://www.googleapis.com/drive")) {
|
|
8753
|
-
let i1 = link.indexOf("/files/");
|
|
8754
|
-
const i2 = link.indexOf("?");
|
|
8755
|
-
if (i1 > 0) {
|
|
8756
|
-
i1 += 7;
|
|
8757
|
-
return i2 > 0 ?
|
|
8758
|
-
link.substring(i1, i2) :
|
|
8759
|
-
link.substring(i1)
|
|
8760
|
-
}
|
|
8761
|
-
}
|
|
8762
|
-
|
|
8763
|
-
throw Error("Unknown Google Drive url format: " + link);
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
}
|
|
8767
|
-
|
|
8768
8610
|
// The MIT License (MIT)
|
|
8769
8611
|
|
|
8770
8612
|
/**
|
|
@@ -8796,7 +8638,7 @@ class Throttle {
|
|
|
8796
8638
|
asyncFunction: asyncFunction,
|
|
8797
8639
|
});
|
|
8798
8640
|
self.dequeue();
|
|
8799
|
-
})
|
|
8641
|
+
})
|
|
8800
8642
|
}
|
|
8801
8643
|
|
|
8802
8644
|
/**
|
|
@@ -8809,10 +8651,10 @@ class Throttle {
|
|
|
8809
8651
|
*/
|
|
8810
8652
|
addAll(promises, options) {
|
|
8811
8653
|
var addedPromises = promises.map(function (promise) {
|
|
8812
|
-
return this.add(promise, options)
|
|
8654
|
+
return this.add(promise, options)
|
|
8813
8655
|
}.bind(this));
|
|
8814
8656
|
|
|
8815
|
-
return Promise.all(addedPromises)
|
|
8657
|
+
return Promise.all(addedPromises)
|
|
8816
8658
|
};
|
|
8817
8659
|
|
|
8818
8660
|
/**
|
|
@@ -8975,9 +8817,6 @@ class IGVXhr {
|
|
|
8975
8817
|
return buffer
|
|
8976
8818
|
}
|
|
8977
8819
|
} else {
|
|
8978
|
-
if (url.startsWith("https://drive.google.com")) {
|
|
8979
|
-
url = getDriveDownloadURL(url);
|
|
8980
|
-
}
|
|
8981
8820
|
if (isGoogleDriveURL(url) || url.startsWith("https://www.dropbox.com")) {
|
|
8982
8821
|
return this.googleThrottle.add(async () => {
|
|
8983
8822
|
return this._loadURL(url, options)
|
|
@@ -9001,9 +8840,15 @@ class IGVXhr {
|
|
|
9001
8840
|
|
|
9002
8841
|
options = options || {};
|
|
9003
8842
|
|
|
9004
|
-
let oauthToken
|
|
9005
|
-
if (
|
|
9006
|
-
|
|
8843
|
+
let oauthToken;
|
|
8844
|
+
if (isGoogleDriveURL(url)) {
|
|
8845
|
+
// Google drive urls always require oAuth
|
|
8846
|
+
oauthToken = await getAccessToken("https://www.googleapis.com/auth/drive.file");
|
|
8847
|
+
} else {
|
|
8848
|
+
oauthToken = options.oauthToken || this.getOauthToken(url);
|
|
8849
|
+
if (oauthToken) {
|
|
8850
|
+
oauthToken = await (typeof oauthToken === 'function' ? oauthToken() : oauthToken);
|
|
8851
|
+
}
|
|
9007
8852
|
}
|
|
9008
8853
|
|
|
9009
8854
|
return new Promise(function (resolve, reject) {
|
|
@@ -9364,8 +9209,10 @@ function addApiKey(url) {
|
|
|
9364
9209
|
}
|
|
9365
9210
|
|
|
9366
9211
|
function addTeamDrive(url) {
|
|
9367
|
-
if (url.includes("
|
|
9212
|
+
if (url.includes("supportsAllDrives")) {
|
|
9368
9213
|
return url
|
|
9214
|
+
} else if (url.includes("supportsTeamDrives")) {
|
|
9215
|
+
return url.replaceAll("supportsTeamDrives", "supportsAllDrives")
|
|
9369
9216
|
} else {
|
|
9370
9217
|
const paramSeparator = url.includes("?") ? "&" : "?";
|
|
9371
9218
|
url = url + paramSeparator + "supportsTeamDrive=true";
|
|
@@ -9380,8 +9227,6 @@ function mapUrl$1(url) {
|
|
|
9380
9227
|
|
|
9381
9228
|
if (url.startsWith("https://www.dropbox.com")) {
|
|
9382
9229
|
return url.replace("//www.dropbox.com", "//dl.dropboxusercontent.com")
|
|
9383
|
-
} else if (url.startsWith("https://drive.google.com")) {
|
|
9384
|
-
return getDriveDownloadURL(url)
|
|
9385
9230
|
} else if (url.includes("//www.broadinstitute.org/igvdata")) {
|
|
9386
9231
|
return url.replace("//www.broadinstitute.org/igvdata", "//data.broadinstitute.org/igvdata")
|
|
9387
9232
|
} else if (url.includes("//igvdata.broadinstitute.org")) {
|
|
@@ -9577,17 +9422,17 @@ class IntervalTree$1 {
|
|
|
9577
9422
|
|
|
9578
9423
|
var searchInterval = new Interval$1(start, end, 0);
|
|
9579
9424
|
|
|
9580
|
-
if (this.root === NIL$1) return []
|
|
9425
|
+
if (this.root === NIL$1) return []
|
|
9581
9426
|
|
|
9582
9427
|
var intervals = searchAll$1.call(this, searchInterval, this.root, []);
|
|
9583
9428
|
|
|
9584
9429
|
if (intervals.length > 1) {
|
|
9585
9430
|
intervals.sort(function (i1, i2) {
|
|
9586
|
-
return i1.low - i2.low
|
|
9431
|
+
return i1.low - i2.low
|
|
9587
9432
|
});
|
|
9588
9433
|
}
|
|
9589
9434
|
|
|
9590
|
-
return intervals
|
|
9435
|
+
return intervals
|
|
9591
9436
|
}
|
|
9592
9437
|
|
|
9593
9438
|
/**
|
|
@@ -9672,7 +9517,7 @@ function searchAll$1(interval, node, results) {
|
|
|
9672
9517
|
searchAll$1.call(this, interval, node.right, results);
|
|
9673
9518
|
}
|
|
9674
9519
|
|
|
9675
|
-
return results
|
|
9520
|
+
return results
|
|
9676
9521
|
}
|
|
9677
9522
|
|
|
9678
9523
|
function leftRotate$1(x) {
|
|
@@ -9751,35 +9596,35 @@ class Interval$1 {
|
|
|
9751
9596
|
|
|
9752
9597
|
equals(other) {
|
|
9753
9598
|
if (!other) {
|
|
9754
|
-
return false
|
|
9599
|
+
return false
|
|
9755
9600
|
}
|
|
9756
9601
|
if (this === other) {
|
|
9757
|
-
return true
|
|
9602
|
+
return true
|
|
9758
9603
|
}
|
|
9759
9604
|
return (this.low === other.low &&
|
|
9760
|
-
this.high === other.high)
|
|
9605
|
+
this.high === other.high)
|
|
9761
9606
|
|
|
9762
9607
|
}
|
|
9763
9608
|
|
|
9764
9609
|
compareTo(other) {
|
|
9765
9610
|
if (this.low < other.low)
|
|
9766
|
-
return -1
|
|
9611
|
+
return -1
|
|
9767
9612
|
if (this.low > other.low)
|
|
9768
|
-
return 1
|
|
9613
|
+
return 1
|
|
9769
9614
|
|
|
9770
9615
|
if (this.high < other.high)
|
|
9771
|
-
return -1
|
|
9616
|
+
return -1
|
|
9772
9617
|
if (this.high > other.high)
|
|
9773
|
-
return 1
|
|
9618
|
+
return 1
|
|
9774
9619
|
|
|
9775
|
-
return 0
|
|
9620
|
+
return 0
|
|
9776
9621
|
}
|
|
9777
9622
|
|
|
9778
9623
|
/**
|
|
9779
9624
|
* Returns true if this interval overlaps the other.
|
|
9780
9625
|
*/
|
|
9781
9626
|
overlaps(other) {
|
|
9782
|
-
|
|
9627
|
+
return (this.low <= other.high && other.low <= this.high)
|
|
9783
9628
|
}
|
|
9784
9629
|
}
|
|
9785
9630
|
|
|
@@ -9824,19 +9669,19 @@ const FeatureUtils = {
|
|
|
9824
9669
|
var start;
|
|
9825
9670
|
var end;
|
|
9826
9671
|
|
|
9827
|
-
if (!features) return
|
|
9672
|
+
if (!features) return
|
|
9828
9673
|
|
|
9829
9674
|
maxRows = maxRows || 10000;
|
|
9830
9675
|
|
|
9831
9676
|
if (!sorted) {
|
|
9832
9677
|
features.sort(function (a, b) {
|
|
9833
|
-
return a.start - b.start
|
|
9678
|
+
return a.start - b.start
|
|
9834
9679
|
});
|
|
9835
9680
|
}
|
|
9836
9681
|
|
|
9837
9682
|
|
|
9838
9683
|
if (features.length === 0) {
|
|
9839
|
-
return []
|
|
9684
|
+
return []
|
|
9840
9685
|
|
|
9841
9686
|
} else {
|
|
9842
9687
|
|
|
@@ -9889,7 +9734,7 @@ const FeatureUtils = {
|
|
|
9889
9734
|
} // while (bucket)
|
|
9890
9735
|
|
|
9891
9736
|
if (!bucket) {
|
|
9892
|
-
break
|
|
9737
|
+
break
|
|
9893
9738
|
}
|
|
9894
9739
|
feature = bucket.pop();
|
|
9895
9740
|
if (0 === bucket.length) {
|
|
@@ -9906,7 +9751,7 @@ const FeatureUtils = {
|
|
|
9906
9751
|
row++;
|
|
9907
9752
|
nextStart = bucketStart;
|
|
9908
9753
|
|
|
9909
|
-
if (allocatedCount === lastAllocatedCount) break
|
|
9754
|
+
if (allocatedCount === lastAllocatedCount) break // Protect from infinite loops
|
|
9910
9755
|
|
|
9911
9756
|
lastAllocatedCount = allocatedCount;
|
|
9912
9757
|
|
|
@@ -9928,13 +9773,13 @@ const FeatureUtils = {
|
|
|
9928
9773
|
findOverlapping: function (featureList, start, end) {
|
|
9929
9774
|
|
|
9930
9775
|
if (!featureList || featureList.length === 0) {
|
|
9931
|
-
return []
|
|
9776
|
+
return []
|
|
9932
9777
|
} else {
|
|
9933
9778
|
const tree = buildIntervalTree$1(featureList);
|
|
9934
9779
|
const intervals = tree.findOverlapping(start, end);
|
|
9935
9780
|
|
|
9936
9781
|
if (intervals.length === 0) {
|
|
9937
|
-
return []
|
|
9782
|
+
return []
|
|
9938
9783
|
} else {
|
|
9939
9784
|
// Trim the list of features in the intervals to those
|
|
9940
9785
|
// overlapping the requested range.
|
|
@@ -9947,7 +9792,7 @@ const FeatureUtils = {
|
|
|
9947
9792
|
const len = intervalFeatures.length;
|
|
9948
9793
|
for (let i = 0; i < len; i++) {
|
|
9949
9794
|
const feature = intervalFeatures[i];
|
|
9950
|
-
if (feature.start > end) break
|
|
9795
|
+
if (feature.start > end) break
|
|
9951
9796
|
else if (feature.end > start) {
|
|
9952
9797
|
featureList.push(feature);
|
|
9953
9798
|
}
|
|
@@ -9955,10 +9800,10 @@ const FeatureUtils = {
|
|
|
9955
9800
|
});
|
|
9956
9801
|
|
|
9957
9802
|
featureList.sort(function (a, b) {
|
|
9958
|
-
return a.start - b.start
|
|
9803
|
+
return a.start - b.start
|
|
9959
9804
|
});
|
|
9960
9805
|
|
|
9961
|
-
return featureList
|
|
9806
|
+
return featureList
|
|
9962
9807
|
}
|
|
9963
9808
|
}
|
|
9964
9809
|
|
|
@@ -9979,7 +9824,7 @@ function buildIntervalTree$1(featureList) {
|
|
|
9979
9824
|
const chunkSize = Math.max(10, Math.round(len / 100));
|
|
9980
9825
|
|
|
9981
9826
|
featureList.sort(function (f1, f2) {
|
|
9982
|
-
return (f1.start === f2.start ? 0 : (f1.start > f2.start ? 1 : -1))
|
|
9827
|
+
return (f1.start === f2.start ? 0 : (f1.start > f2.start ? 1 : -1))
|
|
9983
9828
|
});
|
|
9984
9829
|
|
|
9985
9830
|
for (let i = 0; i < len; i += chunkSize) {
|
|
@@ -9993,7 +9838,7 @@ function buildIntervalTree$1(featureList) {
|
|
|
9993
9838
|
tree.insert(iStart, iEnd, subArray);
|
|
9994
9839
|
}
|
|
9995
9840
|
|
|
9996
|
-
return tree
|
|
9841
|
+
return tree
|
|
9997
9842
|
}
|
|
9998
9843
|
|
|
9999
9844
|
function hexToRGB(hex) {
|
|
@@ -10444,7 +10289,7 @@ const doAutoscale = function (features) {
|
|
|
10444
10289
|
min = Number.MAX_VALUE;
|
|
10445
10290
|
max = -Number.MAX_VALUE;
|
|
10446
10291
|
|
|
10447
|
-
for(let f of features) {
|
|
10292
|
+
for (let f of features) {
|
|
10448
10293
|
if (!Number.isNaN(f.value)) {
|
|
10449
10294
|
min = Math.min(min, f.value);
|
|
10450
10295
|
max = Math.max(max, f.value);
|
|
@@ -10518,19 +10363,6 @@ const isNumber = function (num) {
|
|
|
10518
10363
|
return false
|
|
10519
10364
|
};
|
|
10520
10365
|
|
|
10521
|
-
async function getFilename$1(url) {
|
|
10522
|
-
if (isString$3(url) && url.startsWith("https://drive.google.com")) {
|
|
10523
|
-
// This will fail if Google API key is not defined
|
|
10524
|
-
if (getApiKey() === undefined) {
|
|
10525
|
-
throw Error("Google drive is referenced, but API key is not defined. An API key is required for Google Drive access")
|
|
10526
|
-
}
|
|
10527
|
-
const json = await getDriveFileInfo(url);
|
|
10528
|
-
return json.originalFileName || json.name
|
|
10529
|
-
} else {
|
|
10530
|
-
return getFilename$2(url)
|
|
10531
|
-
}
|
|
10532
|
-
}
|
|
10533
|
-
|
|
10534
10366
|
function prettyBasePairNumber(raw) {
|
|
10535
10367
|
|
|
10536
10368
|
var denom,
|
|
@@ -10593,12 +10425,12 @@ function getElementVerticalDimension(element) {
|
|
|
10593
10425
|
const marginTop = parseInt(style.marginTop);
|
|
10594
10426
|
const marginBottom = parseInt(style.marginBottom);
|
|
10595
10427
|
|
|
10596
|
-
const {
|
|
10428
|
+
const {top, bottom, height} = element.getBoundingClientRect();
|
|
10597
10429
|
return {
|
|
10598
10430
|
top: Math.floor(top) - marginTop,
|
|
10599
10431
|
bottom: Math.floor(bottom) + marginBottom,
|
|
10600
10432
|
height: Math.floor(height) + marginTop + marginBottom
|
|
10601
|
-
}
|
|
10433
|
+
}
|
|
10602
10434
|
}
|
|
10603
10435
|
|
|
10604
10436
|
class Popover {
|
|
@@ -10788,7 +10620,7 @@ function createMenuElements$1(itemList, popover) {
|
|
|
10788
10620
|
return list;
|
|
10789
10621
|
}
|
|
10790
10622
|
|
|
10791
|
-
/*! @license DOMPurify 3.
|
|
10623
|
+
/*! @license DOMPurify 3.3.0 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.3.0/LICENSE */
|
|
10792
10624
|
|
|
10793
10625
|
const {
|
|
10794
10626
|
entries,
|
|
@@ -10974,7 +10806,7 @@ function lookupGetter(object, prop) {
|
|
|
10974
10806
|
}
|
|
10975
10807
|
|
|
10976
10808
|
const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);
|
|
10977
|
-
const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', '
|
|
10809
|
+
const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);
|
|
10978
10810
|
const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);
|
|
10979
10811
|
// List of SVG elements that are disallowed by default.
|
|
10980
10812
|
// We still need to know them so that we can do namespace
|
|
@@ -10988,7 +10820,7 @@ const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongd
|
|
|
10988
10820
|
const text = freeze(['#text']);
|
|
10989
10821
|
|
|
10990
10822
|
const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns', 'slot']);
|
|
10991
|
-
const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
|
|
10823
|
+
const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);
|
|
10992
10824
|
const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);
|
|
10993
10825
|
const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);
|
|
10994
10826
|
|
|
@@ -11095,7 +10927,7 @@ const _createHooksMap = function _createHooksMap() {
|
|
|
11095
10927
|
function createDOMPurify() {
|
|
11096
10928
|
let window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();
|
|
11097
10929
|
const DOMPurify = root => createDOMPurify(root);
|
|
11098
|
-
DOMPurify.version = '3.
|
|
10930
|
+
DOMPurify.version = '3.3.0';
|
|
11099
10931
|
DOMPurify.removed = [];
|
|
11100
10932
|
if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {
|
|
11101
10933
|
// Not running in a browser, provide a factory function
|
|
@@ -11206,6 +11038,21 @@ function createDOMPurify() {
|
|
|
11206
11038
|
let FORBID_TAGS = null;
|
|
11207
11039
|
/* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
|
|
11208
11040
|
let FORBID_ATTR = null;
|
|
11041
|
+
/* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */
|
|
11042
|
+
const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
|
|
11043
|
+
tagCheck: {
|
|
11044
|
+
writable: true,
|
|
11045
|
+
configurable: false,
|
|
11046
|
+
enumerable: true,
|
|
11047
|
+
value: null
|
|
11048
|
+
},
|
|
11049
|
+
attributeCheck: {
|
|
11050
|
+
writable: true,
|
|
11051
|
+
configurable: false,
|
|
11052
|
+
enumerable: true,
|
|
11053
|
+
value: null
|
|
11054
|
+
}
|
|
11055
|
+
}));
|
|
11209
11056
|
/* Decide if ARIA attributes are okay */
|
|
11210
11057
|
let ALLOW_ARIA_ATTR = true;
|
|
11211
11058
|
/* Decide if custom data attributes are okay */
|
|
@@ -11398,16 +11245,24 @@ function createDOMPurify() {
|
|
|
11398
11245
|
}
|
|
11399
11246
|
/* Merge configuration parameters */
|
|
11400
11247
|
if (cfg.ADD_TAGS) {
|
|
11401
|
-
if (
|
|
11402
|
-
|
|
11248
|
+
if (typeof cfg.ADD_TAGS === 'function') {
|
|
11249
|
+
EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
|
|
11250
|
+
} else {
|
|
11251
|
+
if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
|
|
11252
|
+
ALLOWED_TAGS = clone(ALLOWED_TAGS);
|
|
11253
|
+
}
|
|
11254
|
+
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
|
|
11403
11255
|
}
|
|
11404
|
-
addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
|
|
11405
11256
|
}
|
|
11406
11257
|
if (cfg.ADD_ATTR) {
|
|
11407
|
-
if (
|
|
11408
|
-
|
|
11258
|
+
if (typeof cfg.ADD_ATTR === 'function') {
|
|
11259
|
+
EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
|
|
11260
|
+
} else {
|
|
11261
|
+
if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
|
|
11262
|
+
ALLOWED_ATTR = clone(ALLOWED_ATTR);
|
|
11263
|
+
}
|
|
11264
|
+
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
11409
11265
|
}
|
|
11410
|
-
addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
|
|
11411
11266
|
}
|
|
11412
11267
|
if (cfg.ADD_URI_SAFE_ATTR) {
|
|
11413
11268
|
addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
|
|
@@ -11715,7 +11570,7 @@ function createDOMPurify() {
|
|
|
11715
11570
|
return true;
|
|
11716
11571
|
}
|
|
11717
11572
|
/* Remove element if anything forbids its presence */
|
|
11718
|
-
if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
|
|
11573
|
+
if (!(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName])) {
|
|
11719
11574
|
/* Check if we have a custom element to handle */
|
|
11720
11575
|
if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
|
|
11721
11576
|
if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
|
|
@@ -11787,7 +11642,7 @@ function createDOMPurify() {
|
|
|
11787
11642
|
(https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
|
|
11788
11643
|
XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)
|
|
11789
11644
|
We don't need to check the value; it's always URI safe. */
|
|
11790
|
-
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
11645
|
+
if (ALLOW_DATA_ATTR && !FORBID_ATTR[lcName] && regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR, lcName)) ; else if (EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {
|
|
11791
11646
|
if (
|
|
11792
11647
|
// First condition does a very basic check if a) it's basically a valid custom element tagname AND
|
|
11793
11648
|
// b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
|
|
@@ -17194,7 +17049,7 @@ class TrackBase {
|
|
|
17194
17049
|
} else if (isFile(config.url)) {
|
|
17195
17050
|
this.name = config.url.name;
|
|
17196
17051
|
} else if (isString$3(config.url) && !config.url.startsWith("data:")) {
|
|
17197
|
-
this.name = getFilename$
|
|
17052
|
+
this.name = getFilename$1(config.url);
|
|
17198
17053
|
}
|
|
17199
17054
|
|
|
17200
17055
|
this.url = config.url;
|
|
@@ -21154,7 +21009,7 @@ class HtsgetReader {
|
|
|
21154
21009
|
config.format = format.toLowerCase();
|
|
21155
21010
|
config.sourceType = "htsget";
|
|
21156
21011
|
if (!config.name) {
|
|
21157
|
-
config.name =
|
|
21012
|
+
config.name = getFilename$1(config.url);
|
|
21158
21013
|
}
|
|
21159
21014
|
}
|
|
21160
21015
|
} catch (e) {
|
|
@@ -31689,7 +31544,7 @@ class TrackViewport extends Viewport {
|
|
|
31689
31544
|
|
|
31690
31545
|
this.overlayElement.style.top = `-${contentTop}px`;
|
|
31691
31546
|
|
|
31692
|
-
if(!this.checkZoomIn()) return
|
|
31547
|
+
if (!this.checkZoomIn()) return
|
|
31693
31548
|
|
|
31694
31549
|
if (!this.canvas) {
|
|
31695
31550
|
this.repaint();
|
|
@@ -32328,7 +32183,7 @@ class TrackViewport extends Viewport {
|
|
|
32328
32183
|
|
|
32329
32184
|
popupTimerID = setTimeout(() => {
|
|
32330
32185
|
|
|
32331
|
-
const content = this.
|
|
32186
|
+
const content = this.handleTrackClick(event);
|
|
32332
32187
|
if (content) {
|
|
32333
32188
|
|
|
32334
32189
|
if (false === event.shiftKey) {
|
|
@@ -32493,7 +32348,7 @@ class TrackViewport extends Viewport {
|
|
|
32493
32348
|
|
|
32494
32349
|
}
|
|
32495
32350
|
|
|
32496
|
-
|
|
32351
|
+
handleTrackClick(event) {
|
|
32497
32352
|
|
|
32498
32353
|
const clickState = this.createClickState(event);
|
|
32499
32354
|
|
|
@@ -42641,7 +42496,7 @@ async function inferFileFormat(config) {
|
|
|
42641
42496
|
let format;
|
|
42642
42497
|
|
|
42643
42498
|
// First try determining format from file extension
|
|
42644
|
-
const filename = config.filename ||
|
|
42499
|
+
const filename = config.filename || getFilename$1(config.url);
|
|
42645
42500
|
if(filename) {
|
|
42646
42501
|
format = await inferFileFormatFromName(filename);
|
|
42647
42502
|
}
|
|
@@ -67130,7 +66985,7 @@ function createReferenceFrameList(loci, genome, browserFlanking, minimumBases, v
|
|
|
67130
66985
|
})
|
|
67131
66986
|
}
|
|
67132
66987
|
|
|
67133
|
-
const _version = "3.5.
|
|
66988
|
+
const _version = "3.5.4";
|
|
67134
66989
|
function version() {
|
|
67135
66990
|
return _version
|
|
67136
66991
|
}
|
|
@@ -69034,7 +68889,7 @@ class ROIManager {
|
|
|
69034
68889
|
|
|
69035
68890
|
for (let config of configs) {
|
|
69036
68891
|
if (!config.name && config.url) {
|
|
69037
|
-
config.name =
|
|
68892
|
+
config.name = getFilename$1(config.url);
|
|
69038
68893
|
}
|
|
69039
68894
|
if (config.url && !config.format) {
|
|
69040
68895
|
config.format = await inferFileFormat(config);
|
|
@@ -73821,7 +73676,8 @@ class EventEmitter {
|
|
|
73821
73676
|
return handler.apply(scope, args)
|
|
73822
73677
|
});
|
|
73823
73678
|
|
|
73824
|
-
return
|
|
73679
|
+
// The only event that uses the return value is "trackclick", which implicitly assumes a single handler
|
|
73680
|
+
return results[0]
|
|
73825
73681
|
}
|
|
73826
73682
|
}
|
|
73827
73683
|
|
|
@@ -74192,7 +74048,7 @@ class Browser {
|
|
|
74192
74048
|
} else {
|
|
74193
74049
|
let filename = options.filename;
|
|
74194
74050
|
if (!filename) {
|
|
74195
|
-
filename = (options.url ?
|
|
74051
|
+
filename = (options.url ? getFilename$1(options.url) : options.file.name);
|
|
74196
74052
|
}
|
|
74197
74053
|
|
|
74198
74054
|
if (filename.endsWith(".xml")) {
|
|
@@ -74206,10 +74062,8 @@ class Browser {
|
|
|
74206
74062
|
config = {
|
|
74207
74063
|
reference: genomeConfig
|
|
74208
74064
|
};
|
|
74209
|
-
} else
|
|
74065
|
+
} else {
|
|
74210
74066
|
config = await igvxhr.loadJson(urlOrFile);
|
|
74211
|
-
} else {
|
|
74212
|
-
throw Error("Unrecognized session file format:" + filename)
|
|
74213
74067
|
}
|
|
74214
74068
|
}
|
|
74215
74069
|
setDefaults(config, defaults);
|