ckplayer-plus 1.0.5 → 1.0.7
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 +1 -1
- package/dist/ckplayer.js +278 -58
- package/dist/ckplayer.min.js +2 -2
- package/dist/index.cjs +245 -52
- package/dist/index.js +245 -52
- package/dist/react.cjs +245 -52
- package/dist/react.js +245 -52
- package/dist/vue.cjs +245 -52
- package/dist/vue.js +245 -52
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -207,7 +207,7 @@ var require_ckplayer = __commonJS({
|
|
|
207
207
|
cdnFallback: true
|
|
208
208
|
// getPath 失败时是否回退到 jsDelivr(内网可设 false,并配置 pluginPath)
|
|
209
209
|
};
|
|
210
|
-
var ckplayerPlusDefaultCdn = "https://cdn.jsdelivr.net/npm/ckplayer-plus@1.0.
|
|
210
|
+
var ckplayerPlusDefaultCdn = "https://cdn.jsdelivr.net/npm/ckplayer-plus@1.0.7/dist/";
|
|
211
211
|
function ckplayerEmbed(videoObj) {
|
|
212
212
|
var rightMenu = [
|
|
213
213
|
{
|
|
@@ -232,6 +232,11 @@ var require_ckplayer = __commonJS({
|
|
|
232
232
|
var paused = true;
|
|
233
233
|
var loadTime = 0;
|
|
234
234
|
var seekTime = 0;
|
|
235
|
+
var seekRetryTimer = null;
|
|
236
|
+
var seekRetryCount = 0;
|
|
237
|
+
var seekApplyLock = false;
|
|
238
|
+
var decodeRecoverCount = 0;
|
|
239
|
+
var hlsStartPositionUsed = false;
|
|
235
240
|
var oldTime = 0, playTime = 0, firstSeekTime = -1, maxSeeTime = 0;
|
|
236
241
|
var isChangeDef = true;
|
|
237
242
|
var playType = "";
|
|
@@ -397,7 +402,7 @@ var require_ckplayer = __commonJS({
|
|
|
397
402
|
}
|
|
398
403
|
var allowCdn = !vars || vars["cdnFallback"] !== false;
|
|
399
404
|
var cdn = typeof window !== "undefined" && window.ckplayerPlusCdn ? window.ckplayerPlusCdn : ckplayerPlusDefaultCdn;
|
|
400
|
-
if (!allowCdn || !cdn || cdn.indexOf("1.0.
|
|
405
|
+
if (!allowCdn || !cdn || cdn.indexOf("1.0.7") > -1) {
|
|
401
406
|
return folder + "/" + file;
|
|
402
407
|
}
|
|
403
408
|
if (cdn.slice(-1) !== "/") {
|
|
@@ -555,9 +560,86 @@ var require_ckplayer = __commonJS({
|
|
|
555
560
|
changeVideo(video.attr("src"));
|
|
556
561
|
}
|
|
557
562
|
return player;
|
|
563
|
+
}, parseResumeSeekFromVars = function() {
|
|
564
|
+
if (isUndefined(vars["seek"])) {
|
|
565
|
+
return 0;
|
|
566
|
+
}
|
|
567
|
+
if (valType(vars["seek"]) == "number" && vars["seek"] > 0) {
|
|
568
|
+
return vars["seek"];
|
|
569
|
+
}
|
|
570
|
+
if (valType(vars["seek"]) == "string" && vars["seek"] == "cookie" && cookieName) {
|
|
571
|
+
var cke = player.cookie(cookieName);
|
|
572
|
+
if (cke && cke["time"]) {
|
|
573
|
+
return cke["time"];
|
|
574
|
+
}
|
|
575
|
+
return 0;
|
|
576
|
+
}
|
|
577
|
+
if (valType(vars["seek"]) == "string" && vars["seek"] !== "" && !isNaN(parseFloat(vars["seek"]))) {
|
|
578
|
+
return parseFloat(vars["seek"]);
|
|
579
|
+
}
|
|
580
|
+
return 0;
|
|
581
|
+
}, applyResumeSeekState = function(t) {
|
|
582
|
+
if (!t || t <= 0) {
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
seekTime = t;
|
|
586
|
+
maxSeeTime = Math.max(maxSeeTime, t);
|
|
587
|
+
if (firstSeekTime < 0) {
|
|
588
|
+
firstSeekTime = t;
|
|
589
|
+
}
|
|
590
|
+
}, prepareCookieAndSeek = function() {
|
|
591
|
+
if (vars["cookie"]) {
|
|
592
|
+
if (valType(vars["cookie"]) == "array" && vars["cookie"].length >= 2) {
|
|
593
|
+
if (vars["cookie"][0] && valType(vars["cookie"][0]) == "string") {
|
|
594
|
+
cookieName = vars["cookie"][0];
|
|
595
|
+
}
|
|
596
|
+
if (vars["cookie"][1] && valType(vars["cookie"][1]) == "number") {
|
|
597
|
+
cookieTime = vars["cookie"][1];
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
if (valType(vars["cookie"]) == "object" && !isUndefined(vars["cookie"]["name"])) {
|
|
601
|
+
cookieName = vars["cookie"]["name"];
|
|
602
|
+
if (!isUndefined(vars["cookie"]["hour"]) && valType(vars["cookie"]["hour"]) == "number") {
|
|
603
|
+
cookieTime = vars["cookie"]["hour"];
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
if (valType(vars["cookie"]) == "string") {
|
|
607
|
+
cookieName = vars["cookie"];
|
|
608
|
+
}
|
|
609
|
+
if (cookieName) {
|
|
610
|
+
cookieName = cookieName.replace(/[ ]*,[ ]*|[ ]+/g, "").replace(/[ ]*;[ ]*|[ ]+/g, "");
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (!seekTime) {
|
|
614
|
+
applyResumeSeekState(parseResumeSeekFromVars());
|
|
615
|
+
}
|
|
616
|
+
}, destroyStreamPlayers = function() {
|
|
617
|
+
clearSeekRetry();
|
|
618
|
+
seekApplyLock = false;
|
|
619
|
+
hlsStartPositionUsed = false;
|
|
620
|
+
decodeRecoverCount = 0;
|
|
621
|
+
if (hls) {
|
|
622
|
+
try {
|
|
623
|
+
hls.destroy();
|
|
624
|
+
} catch (event2) {
|
|
625
|
+
}
|
|
626
|
+
hls = null;
|
|
627
|
+
}
|
|
628
|
+
if (pugPlayer) {
|
|
629
|
+
try {
|
|
630
|
+
pugPlayer.pause();
|
|
631
|
+
pugPlayer.unload();
|
|
632
|
+
pugPlayer.detachMediaElement();
|
|
633
|
+
pugPlayer.destroy();
|
|
634
|
+
} catch (event2) {
|
|
635
|
+
}
|
|
636
|
+
pugPlayer = null;
|
|
637
|
+
}
|
|
558
638
|
}, changeVideo = function(vstr) {
|
|
559
639
|
var i2 = 0;
|
|
560
640
|
ensureAutoPlug(vstr);
|
|
641
|
+
prepareCookieAndSeek();
|
|
642
|
+
destroyStreamPlayers();
|
|
561
643
|
if (video.attr("src") || video.htm()) {
|
|
562
644
|
player.pause();
|
|
563
645
|
}
|
|
@@ -642,46 +724,6 @@ var require_ckplayer = __commonJS({
|
|
|
642
724
|
if (isChangeDef) {
|
|
643
725
|
checkDefinition();
|
|
644
726
|
}
|
|
645
|
-
if (vars["cookie"]) {
|
|
646
|
-
if (valType(vars["cookie"]) == "array" && vars["cookie"].length >= 2) {
|
|
647
|
-
if (vars["cookie"][0] && valType(vars["cookie"][0]) == "string") {
|
|
648
|
-
cookieName = vars["cookie"][0];
|
|
649
|
-
}
|
|
650
|
-
if (vars["cookie"][1] && valType(vars["cookie"][1]) == "number") {
|
|
651
|
-
cookieTime = vars["cookie"][1];
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
if (valType(vars["cookie"]) == "object" && !isUndefined(vars["cookie"]["name"])) {
|
|
655
|
-
cookieName = vars["cookie"]["name"];
|
|
656
|
-
if (!isUndefined(vars["cookie"]["hour"]) && valType(vars["cookie"]["hour"]) == "number") {
|
|
657
|
-
cookieTime = vars["cookie"]["hour"];
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
if (valType(vars["cookie"]) == "string") {
|
|
661
|
-
cookieName = vars["cookie"];
|
|
662
|
-
}
|
|
663
|
-
if (cookieName) {
|
|
664
|
-
cookieName = cookieName.replace(/[ ]*,[ ]*|[ ]+/g, "").replace(/[ ]*;[ ]*|[ ]+/g, "");
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
if (!isUndefined(vars["seek"]) && !seekTime) {
|
|
668
|
-
if (valType(vars["seek"]) == "number" && vars["seek"] > 0) {
|
|
669
|
-
seekTime = vars["seek"];
|
|
670
|
-
} else if (valType(vars["seek"]) == "string" && vars["seek"] == "cookie" && cookieName) {
|
|
671
|
-
var cke = player.cookie(cookieName);
|
|
672
|
-
if (cke) {
|
|
673
|
-
seekTime = cke["time"];
|
|
674
|
-
}
|
|
675
|
-
} else if (valType(vars["seek"]) == "string" && vars["seek"] !== "" && !isNaN(parseFloat(vars["seek"]))) {
|
|
676
|
-
seekTime = parseFloat(vars["seek"]);
|
|
677
|
-
}
|
|
678
|
-
if (seekTime && seekTime > 0) {
|
|
679
|
-
maxSeeTime = Math.max(maxSeeTime, seekTime);
|
|
680
|
-
if (firstSeekTime < 0) {
|
|
681
|
-
firstSeekTime = seekTime;
|
|
682
|
-
}
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
727
|
}, plugPlayer = function(url) {
|
|
686
728
|
switch (vars["plug"]) {
|
|
687
729
|
case "hls.js":
|
|
@@ -711,11 +753,39 @@ var require_ckplayer = __commonJS({
|
|
|
711
753
|
}, hlsPlayer = function(url) {
|
|
712
754
|
var startHls = function() {
|
|
713
755
|
if (typeof Hls !== "undefined" && !isUndefined(Hls) && Hls.isSupported()) {
|
|
714
|
-
|
|
756
|
+
if (hls) {
|
|
757
|
+
try {
|
|
758
|
+
hls.destroy();
|
|
759
|
+
} catch (event2) {
|
|
760
|
+
}
|
|
761
|
+
hls = null;
|
|
762
|
+
}
|
|
763
|
+
var hlsConf = {
|
|
764
|
+
// 10s 分片流在续播点附近需要略大缓冲,减少卡住转圈
|
|
765
|
+
maxBufferLength: 30,
|
|
766
|
+
maxMaxBufferLength: 60
|
|
767
|
+
};
|
|
768
|
+
var resumeAt = seekTime;
|
|
769
|
+
if (!resumeAt) {
|
|
770
|
+
resumeAt = parseResumeSeekFromVars();
|
|
771
|
+
}
|
|
772
|
+
if (resumeAt && resumeAt > 0 && (isUndefined(vars["live"]) || !vars["live"])) {
|
|
773
|
+
hlsConf.startPosition = resumeAt;
|
|
774
|
+
maxSeeTime = Math.max(maxSeeTime, resumeAt);
|
|
775
|
+
if (firstSeekTime < 0) {
|
|
776
|
+
firstSeekTime = resumeAt;
|
|
777
|
+
}
|
|
778
|
+
seekTime = 0;
|
|
779
|
+
hlsStartPositionUsed = true;
|
|
780
|
+
clearSeekRetry();
|
|
781
|
+
}
|
|
782
|
+
hls = new Hls(hlsConf);
|
|
715
783
|
hls.loadSource(url);
|
|
716
784
|
hls.attachMedia(video);
|
|
717
785
|
hls.on(Hls.Events.MANIFEST_PARSED, function() {
|
|
718
|
-
|
|
786
|
+
if (!hlsStartPositionUsed) {
|
|
787
|
+
applyPendingSeek();
|
|
788
|
+
}
|
|
719
789
|
});
|
|
720
790
|
hls.on(Hls.Events.ERROR, function(event2, data) {
|
|
721
791
|
var code = 9;
|
|
@@ -733,6 +803,13 @@ var require_ckplayer = __commonJS({
|
|
|
733
803
|
}
|
|
734
804
|
}
|
|
735
805
|
}
|
|
806
|
+
if (fatal && data.type === Hls.ErrorTypes.MEDIA_ERROR && hls && typeof hls.recoverMediaError === "function") {
|
|
807
|
+
try {
|
|
808
|
+
hls.recoverMediaError();
|
|
809
|
+
fatal = false;
|
|
810
|
+
} catch (errRecover) {
|
|
811
|
+
}
|
|
812
|
+
}
|
|
736
813
|
CT.error = { code, message: message2 };
|
|
737
814
|
eventTarget("error", CT.error);
|
|
738
815
|
if (fatal) {
|
|
@@ -1414,8 +1491,28 @@ var require_ckplayer = __commonJS({
|
|
|
1414
1491
|
checkTrack();
|
|
1415
1492
|
}
|
|
1416
1493
|
}
|
|
1417
|
-
},
|
|
1418
|
-
if (!
|
|
1494
|
+
}, timeInBuffered = function(t) {
|
|
1495
|
+
if (!video || isUndefined(video.buffered)) {
|
|
1496
|
+
return false;
|
|
1497
|
+
}
|
|
1498
|
+
try {
|
|
1499
|
+
var buf = video.buffered;
|
|
1500
|
+
for (var i2 = 0; i2 < buf.length; i2++) {
|
|
1501
|
+
if (t >= buf.start(i2) - 0.35 && t <= buf.end(i2) + 0.15) {
|
|
1502
|
+
return true;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
} catch (event2) {
|
|
1506
|
+
}
|
|
1507
|
+
return false;
|
|
1508
|
+
}, clearSeekRetry = function() {
|
|
1509
|
+
if (seekRetryTimer) {
|
|
1510
|
+
clearTimeout(seekRetryTimer);
|
|
1511
|
+
seekRetryTimer = null;
|
|
1512
|
+
}
|
|
1513
|
+
seekRetryCount = 0;
|
|
1514
|
+
}, applyPendingSeek = function(force) {
|
|
1515
|
+
if (!seekTime || !video || seekApplyLock) {
|
|
1419
1516
|
return;
|
|
1420
1517
|
}
|
|
1421
1518
|
if (!isUndefined(vars["live"]) && (valType(vars["live"]) == "boolean" && vars["live"] || valType(vars["live"]) == "number")) {
|
|
@@ -1426,18 +1523,96 @@ var require_ckplayer = __commonJS({
|
|
|
1426
1523
|
if (dur && isFinite(dur) && dur > 0 && t >= dur) {
|
|
1427
1524
|
t = Math.max(0, dur - 0.3);
|
|
1428
1525
|
}
|
|
1526
|
+
if (t <= 0) {
|
|
1527
|
+
seekTime = 0;
|
|
1528
|
+
clearSeekRetry();
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1429
1531
|
if (t > 0) {
|
|
1430
1532
|
maxSeeTime = Math.max(maxSeeTime, t);
|
|
1431
1533
|
if (firstSeekTime < 0) {
|
|
1432
1534
|
firstSeekTime = t;
|
|
1433
1535
|
}
|
|
1434
1536
|
}
|
|
1537
|
+
if (hls && typeof hls.startLoad === "function") {
|
|
1538
|
+
clearSeekRetry();
|
|
1539
|
+
seekTime = 0;
|
|
1540
|
+
try {
|
|
1541
|
+
hls.startLoad(t);
|
|
1542
|
+
} catch (event2) {
|
|
1543
|
+
seekTime = t;
|
|
1544
|
+
}
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
var readyEnough = !isUndefined(video.readyState) && video.readyState >= 2;
|
|
1548
|
+
var bufferedOk = timeInBuffered(t);
|
|
1549
|
+
if (!force && !bufferedOk && (!readyEnough || video.readyState < 3)) {
|
|
1550
|
+
seekRetryCount++;
|
|
1551
|
+
if (seekRetryCount <= 50) {
|
|
1552
|
+
if (seekRetryTimer) {
|
|
1553
|
+
clearTimeout(seekRetryTimer);
|
|
1554
|
+
}
|
|
1555
|
+
seekRetryTimer = setTimeout(function() {
|
|
1556
|
+
applyPendingSeek(false);
|
|
1557
|
+
}, 200);
|
|
1558
|
+
return;
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
clearSeekRetry();
|
|
1562
|
+
seekApplyLock = true;
|
|
1435
1563
|
seekTime = 0;
|
|
1436
1564
|
try {
|
|
1437
1565
|
video.currentTime = t;
|
|
1438
1566
|
} catch (event2) {
|
|
1439
1567
|
seekTime = t;
|
|
1568
|
+
seekApplyLock = false;
|
|
1440
1569
|
}
|
|
1570
|
+
setTimeout(function() {
|
|
1571
|
+
seekApplyLock = false;
|
|
1572
|
+
}, 800);
|
|
1573
|
+
}, recoverDecodeError = function() {
|
|
1574
|
+
if (decodeRecoverCount >= 2) {
|
|
1575
|
+
return false;
|
|
1576
|
+
}
|
|
1577
|
+
decodeRecoverCount++;
|
|
1578
|
+
var resumeAt = playTime > 0 ? playTime : vars["seek"] ? parseFloat(vars["seek"]) : 0;
|
|
1579
|
+
if (isNaN(resumeAt) || resumeAt < 0) {
|
|
1580
|
+
resumeAt = 0;
|
|
1581
|
+
}
|
|
1582
|
+
try {
|
|
1583
|
+
if (hls && typeof hls.recoverMediaError === "function") {
|
|
1584
|
+
hls.recoverMediaError();
|
|
1585
|
+
if (resumeAt > 0) {
|
|
1586
|
+
seekTime = resumeAt;
|
|
1587
|
+
seekApplyLock = false;
|
|
1588
|
+
setTimeout(function() {
|
|
1589
|
+
applyPendingSeek(true);
|
|
1590
|
+
}, 300);
|
|
1591
|
+
}
|
|
1592
|
+
return true;
|
|
1593
|
+
}
|
|
1594
|
+
} catch (event2) {
|
|
1595
|
+
}
|
|
1596
|
+
try {
|
|
1597
|
+
var soft = Math.max(0, resumeAt - 1.5);
|
|
1598
|
+
seekTime = resumeAt;
|
|
1599
|
+
seekApplyLock = false;
|
|
1600
|
+
if (video) {
|
|
1601
|
+
video.currentTime = soft;
|
|
1602
|
+
}
|
|
1603
|
+
setTimeout(function() {
|
|
1604
|
+
applyPendingSeek(true);
|
|
1605
|
+
if (video && video.paused && vars["autoplay"]) {
|
|
1606
|
+
try {
|
|
1607
|
+
video.play();
|
|
1608
|
+
} catch (e2) {
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
}, 400);
|
|
1612
|
+
return true;
|
|
1613
|
+
} catch (event2) {
|
|
1614
|
+
}
|
|
1615
|
+
return false;
|
|
1441
1616
|
}, loadedMetaData = function() {
|
|
1442
1617
|
eventTarget("loadedMetaData", {
|
|
1443
1618
|
width: CK.getWidth(),
|
|
@@ -1614,6 +1789,11 @@ var require_ckplayer = __commonJS({
|
|
|
1614
1789
|
if (!isUndefined(errorInfo.message)) {
|
|
1615
1790
|
msg = errorInfo.message;
|
|
1616
1791
|
}
|
|
1792
|
+
if (code === 3 && recoverDecodeError()) {
|
|
1793
|
+
CT.error = { code, message: msg };
|
|
1794
|
+
eventTarget("error", CT.error);
|
|
1795
|
+
return;
|
|
1796
|
+
}
|
|
1617
1797
|
CT.error = { code, message: msg };
|
|
1618
1798
|
showError();
|
|
1619
1799
|
} else {
|
|
@@ -1663,6 +1843,8 @@ var require_ckplayer = __commonJS({
|
|
|
1663
1843
|
eventTarget("error", CT.error);
|
|
1664
1844
|
},
|
|
1665
1845
|
seeked: function() {
|
|
1846
|
+
seekApplyLock = false;
|
|
1847
|
+
decodeRecoverCount = 0;
|
|
1666
1848
|
if (paused) {
|
|
1667
1849
|
player.play();
|
|
1668
1850
|
}
|
|
@@ -2040,7 +2222,8 @@ var require_ckplayer = __commonJS({
|
|
|
2040
2222
|
ad["frontPlay"] = false;
|
|
2041
2223
|
C["ad"].hide();
|
|
2042
2224
|
allBarShow();
|
|
2043
|
-
seekTime =
|
|
2225
|
+
seekTime = 0;
|
|
2226
|
+
applyResumeSeekState(parseResumeSeekFromVars());
|
|
2044
2227
|
if (ad["front"]["video"]) {
|
|
2045
2228
|
changeVideo(vars["video"]);
|
|
2046
2229
|
} else {
|
|
@@ -2614,10 +2797,6 @@ var require_ckplayer = __commonJS({
|
|
|
2614
2797
|
firstSeekTime = target;
|
|
2615
2798
|
}
|
|
2616
2799
|
}
|
|
2617
|
-
try {
|
|
2618
|
-
video.currentTime = target;
|
|
2619
|
-
} catch (event2) {
|
|
2620
|
-
}
|
|
2621
2800
|
return player;
|
|
2622
2801
|
}
|
|
2623
2802
|
if (duration && isFinite(duration) && duration > 0 && target > duration) {
|
|
@@ -2629,6 +2808,20 @@ var require_ckplayer = __commonJS({
|
|
|
2629
2808
|
if (vars["timeScheduleAdjust"] == 5 && target > maxSeeTime && seekTime && Math.abs(seekTime - target) < 0.5) {
|
|
2630
2809
|
maxSeeTime = Math.max(maxSeeTime, target);
|
|
2631
2810
|
}
|
|
2811
|
+
if (target > 0.5 && !timeInBuffered(target) && video.readyState < 3 && !hls) {
|
|
2812
|
+
seekTime = target;
|
|
2813
|
+
applyPendingSeek(false);
|
|
2814
|
+
return player;
|
|
2815
|
+
}
|
|
2816
|
+
if (hls && typeof hls.startLoad === "function") {
|
|
2817
|
+
seekTime = 0;
|
|
2818
|
+
try {
|
|
2819
|
+
hls.startLoad(target);
|
|
2820
|
+
} catch (event2) {
|
|
2821
|
+
seekTime = target;
|
|
2822
|
+
}
|
|
2823
|
+
return player;
|
|
2824
|
+
}
|
|
2632
2825
|
try {
|
|
2633
2826
|
video.currentTime = target;
|
|
2634
2827
|
seekTime = 0;
|
|
@@ -5843,7 +6036,7 @@ var require_ckplayer = __commonJS({
|
|
|
5843
6036
|
if (!isRetry && (!vars || vars["cdnFallback"] !== false)) {
|
|
5844
6037
|
var cdn = typeof window !== "undefined" && window.ckplayerPlusCdn ? window.ckplayerPlusCdn : ckplayerPlusDefaultCdn;
|
|
5845
6038
|
var m2 = String(file).match(/\/(hls\.js|flv\.js|mpegts\.js|language)\/([^/?#]+)(?:[?#].*)?$/i);
|
|
5846
|
-
if (cdn && cdn.indexOf("1.0.
|
|
6039
|
+
if (cdn && cdn.indexOf("1.0.7") === -1 && m2) {
|
|
5847
6040
|
if (cdn.slice(-1) !== "/") {
|
|
5848
6041
|
cdn += "/";
|
|
5849
6042
|
}
|