@js-toolkit/web-utils 1.64.2 → 1.65.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.
- package/EventEmitterListener.js +1 -1
- package/EventListeners.js +1 -1
- package/FullscreenController.js +1 -1
- package/WakeLockController.js +1 -1
- package/blobToDataUrl.js +1 -1
- package/copyToClipboard.js +1 -1
- package/dataUrlToBlob.js +1 -1
- package/fromBase64.d.ts +2 -0
- package/fromBase64.js +1 -0
- package/fullscreen.js +1 -1
- package/getEventAwaiter.js +1 -1
- package/getGeoCoordinates.js +1 -1
- package/getGeoLocality.js +1 -1
- package/iframe/getAutoConnector.js +1 -1
- package/iframe/utils.d.ts +0 -1
- package/iframe/utils.js +1 -1
- package/imageToBlob.js +1 -1
- package/isWebPSupported.js +1 -1
- package/loadImage.js +1 -1
- package/loadScript.d.ts +9 -2
- package/loadScript.js +1 -1
- package/media/Capabilities.js +1 -1
- package/media/MediaStreamController.js +1 -1
- package/media/PipController.js +1 -1
- package/media/TextTracksController/TextTracksController.js +1 -1
- package/media/TextTracksController/utils.js +1 -1
- package/media/parseCueText.js +1 -1
- package/media/resetMedia.js +1 -1
- package/media/toggleNativeSubtitles.js +1 -1
- package/package.json +18 -18
- package/patchConsoleLogging.js +1 -1
- package/performance/getNavigationTiming.js +1 -1
- package/platform/getPlatformInfo.js +1 -1
- package/rafCallback.js +1 -1
- package/saveFileAs.js +1 -1
- package/serviceWorker/ServiceWorkerInstaller.js +1 -1
- package/serviceWorker/utils.js +1 -1
- package/takeScreenshot.d.ts +9 -0
- package/takeScreenshot.js +1 -0
- package/toBase64.d.ts +1 -0
- package/toBase64.js +1 -1
- package/webrtc/PeerConnection.js +1 -1
- package/webrtc/sdputils.js +1 -1
- package/ws/WSController.js +1 -1
- package/takeSnapshot.d.ts +0 -9
- package/takeSnapshot.js +0 -1
package/EventEmitterListener.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isPassiveSupported,isDomEventTarget,isEventTargetLike,normalizeOptions}from"./EventEmitterListener.utils";function getEventTypeError(){return new Error("Event type can not be null.")}function getEventListenerError(){return new Error("Event listener can not be null.")}export class EventEmitterListener{target;interceptor;normalListeners={};captureListeners={};passiveSupported=isPassiveSupported();constructor(e,t){this.target=e,this.interceptor=t,this.target=e}createWrapper(e,t,r,...s){return(...n)=>{r&&this.off(e,t,...s);const i=this.interceptor&&this.interceptor(...n)||n;t(...i)}}getListenerList({event:e,type:t,wrapper:r}={}){const s="normal"===t&&this.normalListeners||"capture"===t&&this.captureListeners||void 0;if(s){const t=e?s[e]&&{[e]:s[e]}:s;return t?Object.values(t).flatMap(
|
|
1
|
+
import{isPassiveSupported,isDomEventTarget,isEventTargetLike,normalizeOptions}from"./EventEmitterListener.utils";function getEventTypeError(){return new Error("Event type can not be null.")}function getEventListenerError(){return new Error("Event listener can not be null.")}export class EventEmitterListener{target;interceptor;normalListeners={};captureListeners={};passiveSupported=isPassiveSupported();constructor(e,t){this.target=e,this.interceptor=t,this.target=e}createWrapper(e,t,r,...s){return(...n)=>{r&&this.off(e,t,...s);const i=this.interceptor&&this.interceptor(...n)||n;t(...i)}}getListenerList({event:e,type:t,wrapper:r}={}){const s="normal"===t&&this.normalListeners||"capture"===t&&this.captureListeners||void 0;if(s){const t=e?s[e]&&{[e]:s[e]}:s;return t?Object.values(t).flatMap(e=>e?Array.from(r?e.values():e.keys()):[]):[]}return this.getListenerList({event:e,type:"normal",wrapper:r}).concat(this.getListenerList({event:e,type:"capture",wrapper:r}))}getListeners({event:e,type:t,wrapper:r}={}){const s="normal"===t&&this.normalListeners||"capture"===t&&this.captureListeners||void 0;if(!s){const t=this.getListeners({event:e,type:"normal",wrapper:r}),s=this.getListeners({event:e,type:"capture",wrapper:r}),n={},i=([e,t])=>{const r=n[e];n[e]=r?r.concat(t):t};return Object.entries(t).forEach(i),Object.entries(s).forEach(i),n}const n=e?s[e]&&{[e]:s[e]}:s;return n?Object.entries(n).reduce((e,[t,s])=>{const n=s?Array.from(r?s.values():s.keys()):[];return n.length>0&&(e[t]=n),e},{}):{}}has(e,t,...r){if(!isDomEventTarget(this.target)){const r=this.normalListeners[e];return!!r&&(t?r.has(t):r.size>0)}const s=r[0],n=!0===s||s&&"object"==typeof s&&(s.capture??!1)?this.captureListeners[e]:this.normalListeners[e];return!!n&&(t?n.has(t):n.size>0)}on(e,t,...r){if(null==e)throw getEventTypeError();if(null==t)throw getEventListenerError();if(!isDomEventTarget(this.target)){const s=this.normalListeners[e]??new Map;this.normalListeners[e]=s;const n=s.get(t)??(this.interceptor?this.createWrapper(e,t,!1,...r):t);return!s.has(t)&&s.set(t,n),isEventTargetLike(this.target)?this.target.addEventListener(e,n,...r):this.target.on(e,n,...r),this}const s=r[0],n=!0===s||s&&"object"==typeof s&&(s.capture??!1),i=(s&&"object"==typeof s&&s.once)??!1;if(n){const n=this.captureListeners[e]??new Map;this.captureListeners[e]=n;const o=n.get(t)??this.createWrapper(e,t,i,...r);!n.has(t)&&n.set(t,o),this.target.addEventListener(e,o,normalizeOptions(s))}else{const n=this.normalListeners[e]??new Map;this.normalListeners[e]=n;const o=n.get(t)??this.createWrapper(e,t,i,...r);!n.has(t)&&n.set(t,o),this.target.addEventListener(e,o,normalizeOptions(s))}return this}once(e,t,...r){if(null==e)throw getEventTypeError();if(null==t)throw getEventListenerError();if(!isDomEventTarget(this.target)){const s=this.normalListeners[e]??new Map;this.normalListeners[e]=s;const n=s.get(t)??this.createWrapper(e,t,!0,...r);return!s.has(t)&&s.set(t,n),isEventTargetLike(this.target)?this.target.addEventListener(e,n,...r):this.target.once?this.target.once(e,n,...r):this.target.on(e,n,...r),this}const s=r[0];return this.on(e,t,{..."object"==typeof s?s:null!=s&&{capture:s},once:!0})}off(e,t,...r){if(!isDomEventTarget(this.target)){const s=this.normalListeners[e],n=s?.get(t);return s&&n&&s.delete(t),0===s?.size&&delete this.normalListeners[e],isEventTargetLike(this.target)?this.target.removeEventListener(e,n??t,...r):this.target.off(e,n??t,...r),this}const s=r[0],n=!0===s||s&&"object"==typeof s&&(s.capture??!1),i=n?this.captureListeners[e]:this.normalListeners[e],o=i?.get(t);return i&&o&&i.delete(t),0===i?.size&&(n?delete this.captureListeners[e]:delete this.normalListeners[e]),this.target.removeEventListener(e,o??t,normalizeOptions(s)),this}removeAllListeners(e){if(e){const t=this.normalListeners[e];t&&t.forEach((t,r)=>this.off(e,r));const r=this.captureListeners[e];r&&r.forEach((t,r)=>this.off(e,r,!0))}else Object.keys(this.normalListeners).forEach(e=>this.removeAllListeners(e)),Object.keys(this.captureListeners).forEach(e=>this.removeAllListeners(e));return this}removeAllListenersBut(...e){return 0===e.length?this.removeAllListeners():(Object.keys(this.normalListeners).forEach(t=>!e.includes(t)&&this.removeAllListeners(t)),Object.keys(this.captureListeners).forEach(t=>!e.includes(t)&&this.removeAllListeners(t)),this)}emit(e,...t){if(null==e)throw getEventTypeError();const[r,...s]=t;return this.getListenerList({event:e,wrapper:!0}).forEach(e=>{e(r,...s)}),this}}
|
package/EventListeners.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventEmitterListener}from"./EventEmitterListener";export class EventListeners{listeners=new Map;getScopes(){return this.listeners.keys()}scope(e,s){const t=s??"",r=this.listeners.get(e)??new Map;!this.listeners.has(e)&&this.listeners.set(e,r);const i=r.get(t)??new EventEmitterListener(e);return!r.has(t)&&r.set(t,i),i}removeAllListeners(e,s){if(e){const t=this.listeners.get(e);s?(t?.get(s)?.removeAllListeners(),t?.delete(s),0===t?.size&&this.listeners.delete(e)):(t?.forEach(
|
|
1
|
+
import{EventEmitterListener}from"./EventEmitterListener";export class EventListeners{listeners=new Map;getScopes(){return this.listeners.keys()}scope(e,s){const t=s??"",r=this.listeners.get(e)??new Map;!this.listeners.has(e)&&this.listeners.set(e,r);const i=r.get(t)??new EventEmitterListener(e);return!r.has(t)&&r.set(t,i),i}removeAllListeners(e,s){if(e){const t=this.listeners.get(e);s?(t?.get(s)?.removeAllListeners(),t?.delete(s),0===t?.size&&this.listeners.delete(e)):(t?.forEach(e=>e.removeAllListeners()),t?.clear(),this.listeners.delete(e))}else this.listeners.forEach(e=>{e.forEach(e=>e.removeAllListeners()),e.clear()}),this.listeners.clear();return this}}
|
package/FullscreenController.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{hasIn}from"@js-toolkit/utils/hasIn";import{toggleNativeSubtitles}from"./media/toggleNativeSubtitles";import{fullscreen}from"./fullscreen";import{enterPseudoFullscreen}from"./fullscreenUtils";export class FullscreenController extends EventEmitter{element;options;static isApiAvailable(){return fullscreen.isApiEnabled()}get Events(){return FullscreenController.Events}fallback;exitPseudoFullscreen;constructor(e,t={}){super(),this.element=e,this.options=t,this.setOptions(t)}unbind(){if(fullscreen.names){const{names:e}=fullscreen;this.element.removeEventListener(e.changeEventName,this.nativeChangeHandler),this.element.removeEventListener(e.errorEventName,this.nativeErrorHandler)}this.fallback instanceof HTMLVideoElement&&(this.fallback.removeEventListener("webkitbeginfullscreen",this.videoBeginFullscreenHandler),this.fallback.removeEventListener("webkitendfullscreen",this.videoEndFullscreenHandler),this.fallback=void 0)}setOptions(e){if(this.unbind(),this.options=e??{},this.fallback=this.options.fallback,fullscreen.names&&fullscreen.isApiEnabled()){const{names:e}=fullscreen;this.element.addEventListener(e.changeEventName,this.nativeChangeHandler),this.element.addEventListener(e.errorEventName,this.nativeErrorHandler)}else this.fallback instanceof HTMLVideoElement&&(this.fallback.addEventListener("webkitbeginfullscreen",this.videoBeginFullscreenHandler),this.fallback.addEventListener("webkitendfullscreen",this.videoEndFullscreenHandler))}isAvailable(){return fullscreen.isApiEnabled()||"pseudo"===this.fallback||this.fallback instanceof HTMLVideoElement&&!!this.fallback.webkitEnterFullscreen&&!!this.fallback.webkitSupportsFullscreen}isFullscreen(){return!!this.getCurrentElement()}isPseudoFullscreen(){return this.isFullscreen()&&!!this.exitPseudoFullscreen}getCurrentElement(){if(fullscreen.isApiEnabled()){if(fullscreen.getElement()===this.element)return this.element}else{if(this.exitPseudoFullscreen)return this.element;if(this.fallback instanceof HTMLVideoElement&&this.fallback.webkitDisplayingFullscreen)return this.fallback}return null}nativeChangeHandler=()=>{this.emit(this.Events.Change,{fullscreen:this.isFullscreen(),type:"native"})};nativeErrorHandler=e=>{this.emit(this.Events.Error,{error:e,type:"native"})};videoBeginFullscreenHandler=(()=>{const e=()=>{const t=this.fallback;e.controls=t.controls,e.nativeSubtitles=hasIn(this.options,"toggleNativeSubtitles")&&this.options.toggleNativeSubtitles&&t.textTracks.length>0,e.nativeSubtitles&&toggleNativeSubtitles(!0,t.textTracks),this.emit(this.Events.Change,{fullscreen:!0,type:"video"})};return e.nativeSubtitles=void 0,e.controls=void 0,e})();videoEndFullscreenHandler=()=>{const e=this.fallback;null!=this.videoBeginFullscreenHandler.controls&&(e.controls=this.videoBeginFullscreenHandler.controls),this.videoBeginFullscreenHandler.nativeSubtitles&&toggleNativeSubtitles(!1,e.textTracks),this.emit(this.Events.Change,{fullscreen:!1,type:"video"})};request(e={}){return new Promise((
|
|
1
|
+
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{hasIn}from"@js-toolkit/utils/hasIn";import{toggleNativeSubtitles}from"./media/toggleNativeSubtitles";import{fullscreen}from"./fullscreen";import{enterPseudoFullscreen}from"./fullscreenUtils";export class FullscreenController extends EventEmitter{element;options;static isApiAvailable(){return fullscreen.isApiEnabled()}get Events(){return FullscreenController.Events}fallback;exitPseudoFullscreen;constructor(e,t={}){super(),this.element=e,this.options=t,this.setOptions(t)}unbind(){if(fullscreen.names){const{names:e}=fullscreen;this.element.removeEventListener(e.changeEventName,this.nativeChangeHandler),this.element.removeEventListener(e.errorEventName,this.nativeErrorHandler)}this.fallback instanceof HTMLVideoElement&&(this.fallback.removeEventListener("webkitbeginfullscreen",this.videoBeginFullscreenHandler),this.fallback.removeEventListener("webkitendfullscreen",this.videoEndFullscreenHandler),this.fallback=void 0)}setOptions(e){if(this.unbind(),this.options=e??{},this.fallback=this.options.fallback,fullscreen.names&&fullscreen.isApiEnabled()){const{names:e}=fullscreen;this.element.addEventListener(e.changeEventName,this.nativeChangeHandler),this.element.addEventListener(e.errorEventName,this.nativeErrorHandler)}else this.fallback instanceof HTMLVideoElement&&(this.fallback.addEventListener("webkitbeginfullscreen",this.videoBeginFullscreenHandler),this.fallback.addEventListener("webkitendfullscreen",this.videoEndFullscreenHandler))}isAvailable(){return fullscreen.isApiEnabled()||"pseudo"===this.fallback||this.fallback instanceof HTMLVideoElement&&!!this.fallback.webkitEnterFullscreen&&!!this.fallback.webkitSupportsFullscreen}isFullscreen(){return!!this.getCurrentElement()}isPseudoFullscreen(){return this.isFullscreen()&&!!this.exitPseudoFullscreen}getCurrentElement(){if(fullscreen.isApiEnabled()){if(fullscreen.getElement()===this.element)return this.element}else{if(this.exitPseudoFullscreen)return this.element;if(this.fallback instanceof HTMLVideoElement&&this.fallback.webkitDisplayingFullscreen)return this.fallback}return null}nativeChangeHandler=()=>{this.emit(this.Events.Change,{fullscreen:this.isFullscreen(),type:"native"})};nativeErrorHandler=e=>{this.emit(this.Events.Error,{error:e,type:"native"})};videoBeginFullscreenHandler=(()=>{const e=()=>{const t=this.fallback;e.controls=t.controls,e.nativeSubtitles=hasIn(this.options,"toggleNativeSubtitles")&&this.options.toggleNativeSubtitles&&t.textTracks.length>0,e.nativeSubtitles&&toggleNativeSubtitles(!0,t.textTracks),this.emit(this.Events.Change,{fullscreen:!0,type:"video"})};return e.nativeSubtitles=void 0,e.controls=void 0,e})();videoEndFullscreenHandler=()=>{const e=this.fallback;null!=this.videoBeginFullscreenHandler.controls&&(e.controls=this.videoBeginFullscreenHandler.controls),this.videoBeginFullscreenHandler.nativeSubtitles&&toggleNativeSubtitles(!1,e.textTracks),this.emit(this.Events.Change,{fullscreen:!1,type:"video"})};request(e={}){return new Promise((t,n)=>{if(this.isFullscreen())return void t();if(fullscreen.isApiEnabled())return void fullscreen.request(this.element,e).then(t).catch(n);if("pseudo"===this.fallback)return this.exitPseudoFullscreen=enterPseudoFullscreen(this.element),this.emit(this.Events.Change,{fullscreen:!0,type:"pseudo"}),void t();const l=this.fallback instanceof HTMLVideoElement&&this.fallback||void 0;if(l?.webkitEnterFullscreen&&l.webkitSupportsFullscreen){const e=()=>{l.removeEventListener("webkitbeginfullscreen",e),t()};return l.addEventListener("webkitbeginfullscreen",e),void l.webkitEnterFullscreen()}n(new fullscreen.UnavailableError)})}exit(){return new Promise((e,t)=>{if(!this.isFullscreen())return void e();if(fullscreen.isApiEnabled())return void fullscreen.exit().then(e).catch(t);if(this.exitPseudoFullscreen)return this.exitPseudoFullscreen(),this.exitPseudoFullscreen=void 0,this.emit(this.Events.Change,{fullscreen:!1,type:"pseudo"}),void e();const n=this.fallback instanceof HTMLVideoElement&&this.fallback||void 0;if(n?.webkitExitFullscreen&&n.webkitSupportsFullscreen){const t=()=>{n.removeEventListener("webkitendfullscreen",t),e()};return n.addEventListener("webkitendfullscreen",t),void n.webkitExitFullscreen()}t(new fullscreen.UnavailableError)})}destroy(){return this.exit().then(()=>new Promise(e=>{requestAnimationFrame(()=>{this.removeAllListeners(),this.unbind(),e()})}))}[Symbol.asyncDispose](){return this.destroy()}}!function(e){let t;!function(e){e.Change="change",e.Error="error"}(t=e.Events||(e.Events={}))}(FullscreenController||(FullscreenController={}));
|
package/WakeLockController.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{hasIn}from"@js-toolkit/utils/hasIn";export class WakeLockController extends EventEmitter{static isApiAvailable(){return hasIn(navigator,"wakeLock")&&null!=navigator.wakeLock}wakelock;releasing=!1;relockOnVisible=!1;restoreWakeLock=()=>{"visible"===document.visibilityState&&this.relockOnVisible&&(this.relockOnVisible=!1,this.request().catch(
|
|
1
|
+
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{hasIn}from"@js-toolkit/utils/hasIn";export class WakeLockController extends EventEmitter{static isApiAvailable(){return hasIn(navigator,"wakeLock")&&null!=navigator.wakeLock}wakelock;releasing=!1;relockOnVisible=!1;restoreWakeLock=()=>{"visible"===document.visibilityState&&this.relockOnVisible&&(this.relockOnVisible=!1,this.request().catch(e=>this.emit("error",{error:e})))};onRelease=()=>{this.wakelock&&(this.wakelock.removeEventListener("release",this.onRelease),this.wakelock=void 0,this.releasing?document.removeEventListener("visibilitychange",this.restoreWakeLock):"hidden"===document.visibilityState&&(this.relockOnVisible=!0,document.addEventListener("visibilitychange",this.restoreWakeLock)),this.emit("deactivated"))};isActive(){return!!this.wakelock&&!this.wakelock.released}async request(){if(!this.wakelock){try{this.wakelock=await navigator.wakeLock.request("screen")}catch(e){if("visible"===document.visibilityState)throw e;return this.relockOnVisible=!0,document.addEventListener("visibilitychange",this.restoreWakeLock),void this.emit("error",{error:e})}this.relockOnVisible=!1,this.wakelock.addEventListener("release",this.onRelease),this.emit("activated")}}async release(){if(this.wakelock&&!this.wakelock.released)try{this.releasing=!0,await this.wakelock.release(),this.relockOnVisible=!1}finally{this.releasing=!1}}async destroy(){await this.release(),this.removeAllListeners()}[Symbol.asyncDispose](){return this.destroy()}}
|
package/blobToDataUrl.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function blobToDataUrl(e){return new Promise((
|
|
1
|
+
export function blobToDataUrl(e){return new Promise((r,o)=>{const n=new FileReader;n.onload=()=>{r(n.result)},n.onerror=o,n.readAsDataURL(e)})}
|
package/copyToClipboard.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function copyToClipboard(e){return navigator.clipboard?navigator.clipboard.writeText(e):new Promise((
|
|
1
|
+
export function copyToClipboard(e){return navigator.clipboard?navigator.clipboard.writeText(e):new Promise((o,t)=>{const n=document.createElement("textarea");n.textContent=e,n.style.position="fixed",n.style.bottom="-100px",n.readOnly=!0,document.body.appendChild(n);const c=document.createRange();c.selectNode(n);const a=window.getSelection();if(a){a.removeAllRanges(),a.addRange(c),n.setSelectionRange(0,999999);try{document.execCommand("copy",!1),o()}catch(e){t(e)}finally{a.removeAllRanges(),document.body.removeChild(n)}}else t(new Error("No selection for copy to clipboard."))})}
|
package/dataUrlToBlob.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function dataUrlToBlob(t){const[e,n]=t.split(","),r=window.atob(n),o=e.split(":")[1].split(";")[0],l=new ArrayBuffer(r.length),a=new Uint8Array(l);for(let t=0;t<
|
|
1
|
+
export function dataUrlToBlob(t){const[e,n]=t.split(","),r=window.atob(n),o=e.split(":")[1].split(";")[0],l=new ArrayBuffer(r.length),a=new Uint8Array(l),{length:i}=r;for(let t=0;t<i;t+=1)a[t]=r.charCodeAt(t);return new Blob([l],{type:o})}
|
package/fromBase64.d.ts
ADDED
package/fromBase64.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function fromBase64(e){const o=window.atob(e);return window.TextDecoder?(new TextDecoder).decode(Uint8Array.from(o,e=>e.codePointAt(0))):decodeURIComponent(escape(o))}
|
package/fullscreen.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{es5ErrorCompat}from"@js-toolkit/utils/es5ErrorCompat";import{promisify}from"@js-toolkit/utils/promisify";export class FullscreenUnavailableError extends Error{constructor(){super("Fullscreen is not available"),es5ErrorCompat(this,FullscreenUnavailableError)}}export var fullscreen;!function(e){e.names=[{requestFullscreenName:"requestFullscreen",exitFullscreenName:"exitFullscreen",fullscreenElementName:"fullscreenElement",fullscreenEnabledName:"fullscreenEnabled",changeEventName:"fullscreenchange",errorEventName:"fullscreenerror"},{requestFullscreenName:"webkitRequestFullscreen",exitFullscreenName:"webkitExitFullscreen",fullscreenElementName:"webkitFullscreenElement",fullscreenEnabledName:"webkitFullscreenEnabled",changeEventName:"webkitfullscreenchange",errorEventName:"webkitfullscreenerror"},{requestFullscreenName:"webkitRequestFullScreen",exitFullscreenName:"webkitCancelFullScreen",fullscreenElementName:"webkitCurrentFullScreenElement",fullscreenEnabledName:"webkitCancelFullScreen",changeEventName:"webkitfullscreenchange",errorEventName:"webkitfullscreenerror"},{requestFullscreenName:"mozRequestFullScreen",exitFullscreenName:"mozCancelFullScreen",fullscreenElementName:"mozFullScreenElement",fullscreenEnabledName:"mozFullScreenEnabled",changeEventName:"mozfullscreenchange",errorEventName:"mozfullscreenerror"},{requestFullscreenName:"msRequestFullscreen",exitFullscreenName:"msExitFullscreen",fullscreenElementName:"msFullscreenElement",fullscreenEnabledName:"msFullscreenEnabled",changeEventName:"MSFullscreenChange",errorEventName:"MSFullscreenError"}].find((
|
|
1
|
+
import{es5ErrorCompat}from"@js-toolkit/utils/es5ErrorCompat";import{promisify}from"@js-toolkit/utils/promisify";export class FullscreenUnavailableError extends Error{constructor(){super("Fullscreen is not available"),es5ErrorCompat(this,FullscreenUnavailableError)}}export var fullscreen;!function(e){e.names=[{requestFullscreenName:"requestFullscreen",exitFullscreenName:"exitFullscreen",fullscreenElementName:"fullscreenElement",fullscreenEnabledName:"fullscreenEnabled",changeEventName:"fullscreenchange",errorEventName:"fullscreenerror"},{requestFullscreenName:"webkitRequestFullscreen",exitFullscreenName:"webkitExitFullscreen",fullscreenElementName:"webkitFullscreenElement",fullscreenEnabledName:"webkitFullscreenEnabled",changeEventName:"webkitfullscreenchange",errorEventName:"webkitfullscreenerror"},{requestFullscreenName:"webkitRequestFullScreen",exitFullscreenName:"webkitCancelFullScreen",fullscreenElementName:"webkitCurrentFullScreenElement",fullscreenEnabledName:"webkitCancelFullScreen",changeEventName:"webkitfullscreenchange",errorEventName:"webkitfullscreenerror"},{requestFullscreenName:"mozRequestFullScreen",exitFullscreenName:"mozCancelFullScreen",fullscreenElementName:"mozFullScreenElement",fullscreenEnabledName:"mozFullScreenEnabled",changeEventName:"mozfullscreenchange",errorEventName:"mozfullscreenerror"},{requestFullscreenName:"msRequestFullscreen",exitFullscreenName:"msExitFullscreen",fullscreenElementName:"msFullscreenElement",fullscreenEnabledName:"msFullscreenEnabled",changeEventName:"MSFullscreenChange",errorEventName:"MSFullscreenError"}].find(({exitFullscreenName:e})=>e in document);const n={change:e.names?.changeEventName,error:e.names?.errorEventName};function r(){if(!e.names)throw new e.UnavailableError;return Boolean(document[e.names.fullscreenElementName])}function l(e,r,l){const a=n[e];a&&document.addEventListener(a,r,l)}function a(e,r,l){const a=n[e];a&&document.removeEventListener(a,r,l)}function t(n,r){return new Promise((t,s)=>{if(!e.names)throw new e.UnavailableError;const c=()=>{a("change",c),a("error",u),t()},u=e=>{a("change",c),a("error",u),s(e)};l("change",c),l("error",u),n[e.names.requestFullscreenName](r)})}function s(){return new Promise((n,t)=>{if(!e.names)throw new e.UnavailableError;if(!r())return void n();const s=()=>{a("change",s),a("error",c),n()},c=e=>{a("change",s),a("error",c),t(e)};l("change",s),l("error",c),document[e.names.exitFullscreenName]()})}e.UnavailableError=FullscreenUnavailableError,e.isApiAvailable=function(){return!!e.names},e.isApiEnabled=function(){return!!e.names&&Boolean(document[e.names.fullscreenEnabledName])},e.isFullscreen=r,e.getElement=function(){if(!e.names)throw new e.UnavailableError;return document[e.names.fullscreenElementName]},e.on=l,e.off=a,e.request=t,e.exit=s,e.toggle=function(e){return promisify(()=>r()?s():t(e))},e.onChange=function(e){l("change",e)},e.onError=function(e){l("error",e)}}(fullscreen||(fullscreen={}));
|
package/getEventAwaiter.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getAwaiter}from"@js-toolkit/utils/getAwaiter";import{EventEmitterListener}from"./EventEmitterListener";import{isEventEmitterLike}from"./EventEmitterListener.utils";export function getEventAwaiter(e,t,r,{ignoreResolve:i,eventToError:o,lazy:n=!0,...s}={}){const E=getAwaiter({lazy:n,...s}),a=Array.isArray(t)?t:[t],f=Array.isArray(r)&&r||r&&[r]||[],m=isEventEmitterLike(e)?e:new EventEmitterListener(e),v=e=>{!(!!i&&i(e))&&E.resolve(e)},c=e=>{const t=o?o(e):e;null!=t&&E.reject(t)},l=()=>{a.forEach(
|
|
1
|
+
import{getAwaiter}from"@js-toolkit/utils/getAwaiter";import{EventEmitterListener}from"./EventEmitterListener";import{isEventEmitterLike}from"./EventEmitterListener.utils";export function getEventAwaiter(e,t,r,{ignoreResolve:i,eventToError:o,lazy:n=!0,...s}={}){const E=getAwaiter({lazy:n,...s}),a=Array.isArray(t)?t:[t],f=Array.isArray(r)&&r||r&&[r]||[],m=isEventEmitterLike(e)?e:new EventEmitterListener(e),v=e=>{!(!!i&&i(e))&&E.resolve(e)},c=e=>{const t=o?o(e):e;null!=t&&E.reject(t)},l=()=>{a.forEach(e=>m.off(e,v)),f.forEach(e=>m.off(e,c))},A=E.resolve;E.resolve=(...e)=>(l(),A(...e));const y=E.reject;return E.reject=(...e)=>{y(...e),l()},a.forEach(e=>m.on(e,v)),f.forEach(e=>m.on(e,c)),E}
|
package/getGeoCoordinates.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function getGeoCoordinates({timeout:e=1e4,maximumAge:o=6e4,...t}={}){return new Promise((
|
|
1
|
+
export function getGeoCoordinates({timeout:e=1e4,maximumAge:o=6e4,...t}={}){return new Promise((i,m)=>{navigator.geolocation.getCurrentPosition(e=>i(e),e=>m(e),{timeout:e,maximumAge:o,...t})})}
|
package/getGeoLocality.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getErrorMessage}from"@js-toolkit/utils/getErrorMessage";export function getGeoLocality({longitude:e,latitude:r,lang:o}){const s=new URL("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode");return s.searchParams.set("f","json"),s.searchParams.set("featureTypes","Locality"),s.searchParams.set("location",`{ x: ${e}, y: ${r} }`),o&&s.searchParams.set("langCode",o),window.fetch(s.toString()).then(
|
|
1
|
+
import{getErrorMessage}from"@js-toolkit/utils/getErrorMessage";export function getGeoLocality({longitude:e,latitude:r,lang:o}){const s=new URL("https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode");return s.searchParams.set("f","json"),s.searchParams.set("featureTypes","Locality"),s.searchParams.set("location",`{ x: ${e}, y: ${r} }`),o&&s.searchParams.set("langCode",o),window.fetch(s.toString()).then(e=>e.json()).then(e=>{const{address:r,error:o}=e;if(o)throw new Error(getErrorMessage(o),{cause:o});return r.PlaceName||r.LongLabel||r.ShortLabel||""})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{v4 as uuid}from"uuid";import log from"@js-toolkit/utils/log";import{onDOMReady}from"../onDOMReady";import{isPingMessage,isTargetReadyMessage}from"./messages";import{isWindowProxy,readTargets}from"./utils";import{getOriginFromMessage}from"./getOriginFromMessage";export{getClientMessages,getHostMessages}from"./messages";export function getAutoConnector({id:e,label:t,strictTargets:o=!0,messagesTypes:s,channel:n,logger:i=log.getLogger("AutoConnector"),onSendData:r,onConnect:a}){const d=e||uuid(),g=t||d,c=new Map,f="open"===n?new Map:void 0;let u,l;const p=(e,t,o,s,n)=>{if(window!==t)if(isWindowProxy(t)){t.postMessage(e,o,n);const r=t===window.parent?"iframe parent":"iframe";i.v1(`${g}: Post message to ${r} (uid=${s},self.uid=${d},origin=${o}):`,e)}else t.postMessage(e,n&&{transfer:n}),i.v1(`${g}: Post message to MessageEventSource (uid=${s},self.uid=${d}):`,e)},m=(e,t,o)=>{p({uid:d,type:s.Ping},e,t,o)},h=e=>{if(!e.source||e.source===window)return;if(!isPingMessage(e.data,s)&&!isTargetReadyMessage(e.data,s))return;if(e.data.uid===d)return;const t=e.source,l=e.data.uid;if(i.v1(`${g}: Receive message from iframe (uid=${l},self.uid=${d},origin=${e.origin}):`,e.data),o&&u&&!u.has(t))return void i.v1(`${g}: Could not find target (uid=${l},self.uid=${d}) by message.source.`);const h=getOriginFromMessage(e);if(isPingMessage(e.data,s)&&!c.get(l)?.Ping)return c.set(l,{...c.get(l),Ping:!0}),void m(t,h,l);let w=!1;if(c.get(l)?.Ping&&!c.get(l)?.SelfReady){c.set(l,{...c.get(l),SelfReady:!0});const e={target:t,origin:h},o=f?(()=>{const t=f.get(l)?.[0]??new MessageChannel;return f.set(l,[t,e]),t.port2})():void 0;((e,t,o,n,i)=>{p({uid:d,type:s.SelfReady,data:e},t,o,n,i?[i]:void 0)})(r?r(e):void 0,t,h,l,o),w=!1}if(isTargetReadyMessage(e.data,s)&&c.get(l)?.SelfReady){c.delete(l),u?.delete(t);const o=(()=>{if("open"===n){const e=f?.get(l)?.[0].port1;if(!e)throw new Error("Something went wrong: MessageChannel is not created despite the fact that the `channel` option is `open`.");return e}if("use"===n){const t=e.ports[0];if(!t)throw new Error("MessagePort is not received despite the fact that the `channel` option is `use`. The `channel` option of connector on another side must be equals `open`.");return t}})(),{data:s}=e.data,r=()=>{i.v1(`${g}: Connection established (self.uid=${d} + uid=${l}).`),a({data:s,target:t,origin:h},o)};w?setTimeout(r,0):r()}},w=()=>{l&&(l(),l=void 0)};return{start:(e,t={})=>{if(l&&!t.append)return void i.warn(`${g}: Already started. You should first call \`stop\`.`);if(t.append){const e=u;w(),u=e}const o=()=>{const o=(()=>{const t="function"==typeof e?e():e;return t.length>0?t:void 0})(),s=o&&readTargets(o);if(!s)return;const n=new Set(s);t.append?(u||(u=new Set),n.forEach(
|
|
1
|
+
import{v4 as uuid}from"uuid";import log from"@js-toolkit/utils/log";import{onDOMReady}from"../onDOMReady";import{isPingMessage,isTargetReadyMessage}from"./messages";import{isWindowProxy,readTargets}from"./utils";import{getOriginFromMessage}from"./getOriginFromMessage";export{getClientMessages,getHostMessages}from"./messages";export function getAutoConnector({id:e,label:t,strictTargets:o=!0,messagesTypes:s,channel:n,logger:i=log.getLogger("AutoConnector"),onSendData:r,onConnect:a}){const d=e||uuid(),g=t||d,c=new Map,f="open"===n?new Map:void 0;let u,l;const p=(e,t,o,s,n)=>{if(window!==t)if(isWindowProxy(t)){t.postMessage(e,o,n);const r=t===window.parent?"iframe parent":"iframe";i.v1(`${g}: Post message to ${r} (uid=${s},self.uid=${d},origin=${o}):`,e)}else t.postMessage(e,n&&{transfer:n}),i.v1(`${g}: Post message to MessageEventSource (uid=${s},self.uid=${d}):`,e)},m=(e,t,o)=>{p({uid:d,type:s.Ping},e,t,o)},h=e=>{if(!e.source||e.source===window)return;if(!isPingMessage(e.data,s)&&!isTargetReadyMessage(e.data,s))return;if(e.data.uid===d)return;const t=e.source,l=e.data.uid;if(i.v1(`${g}: Receive message from iframe (uid=${l},self.uid=${d},origin=${e.origin}):`,e.data),o&&u&&!u.has(t))return void i.v1(`${g}: Could not find target (uid=${l},self.uid=${d}) by message.source.`);const h=getOriginFromMessage(e);if(isPingMessage(e.data,s)&&!c.get(l)?.Ping)return c.set(l,{...c.get(l),Ping:!0}),void m(t,h,l);let w=!1;if(c.get(l)?.Ping&&!c.get(l)?.SelfReady){c.set(l,{...c.get(l),SelfReady:!0});const e={target:t,origin:h},o=f?(()=>{const t=f.get(l)?.[0]??new MessageChannel;return f.set(l,[t,e]),t.port2})():void 0;((e,t,o,n,i)=>{p({uid:d,type:s.SelfReady,data:e},t,o,n,i?[i]:void 0)})(r?r(e):void 0,t,h,l,o),w=!1}if(isTargetReadyMessage(e.data,s)&&c.get(l)?.SelfReady){c.delete(l),u?.delete(t);const o=(()=>{if("open"===n){const e=f?.get(l)?.[0].port1;if(!e)throw new Error("Something went wrong: MessageChannel is not created despite the fact that the `channel` option is `open`.");return e}if("use"===n){const t=e.ports[0];if(!t)throw new Error("MessagePort is not received despite the fact that the `channel` option is `use`. The `channel` option of connector on another side must be equals `open`.");return t}})(),{data:s}=e.data,r=()=>{i.v1(`${g}: Connection established (self.uid=${d} + uid=${l}).`),a({data:s,target:t,origin:h},o)};w?setTimeout(r,0):r()}},w=()=>{l&&(l(),l=void 0)};return{start:(e,t={})=>{if(l&&!t.append)return void i.warn(`${g}: Already started. You should first call \`stop\`.`);if(t.append){const e=u;w(),u=e}const o=()=>{const o=(()=>{const t="function"==typeof e?e():e;return t.length>0?t:void 0})(),s=o&&readTargets(o);if(!s)return;const n=new Set(s);t.append?(u||(u=new Set),n.forEach(e=>u.add(e))):u=n,window.addEventListener("message",h);(t.append?n:u).forEach(e=>{e!==window&&m(e,"*","")})},s="function"==typeof e?onDOMReady(o):o();l=()=>{s&&s(),window.removeEventListener("message",h),u=void 0}},stop:w,isStarted:()=>!!l,close:e=>{const t=e instanceof Set?e:new Set(readTargets(e));if(0!==t.size&&(f&&f.forEach(([e,o],s)=>{t.has(o.target)&&(e.port1.close(),e.port2.close(),f.delete(s))}),u)){const e=u;t.forEach(t=>e.delete(t))}},destroy:()=>{w(),c.clear(),f&&(f.forEach(([e])=>{e.port1.close(),e.port2.close()}),f.clear())},[Symbol.dispose](){this.destroy()}}}
|
package/iframe/utils.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export type Target = HTMLIFrameElement | Window;
|
|
2
|
-
export declare function selectFrames(): HTMLCollectionOf<HTMLIFrameElement>;
|
|
3
2
|
export declare function findTarget<T extends Target>(source: Window, targets: ArrayLike<T>): T | undefined;
|
|
4
3
|
export declare function isWindowProxy(target: MessageEventSource): target is Window;
|
|
5
4
|
export declare function readTargets(list: ArrayLike<Target>): Window[];
|
package/iframe/utils.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function findTarget(e,n){const{length:t}=n;for(let o=0;o<t;o+=1){const t=n[o];if((t instanceof HTMLIFrameElement?t.contentWindow:t)===e)return t}}export function isWindowProxy(e){return!(void 0!==window.MessagePort&&e instanceof MessagePort||void 0!==window.ServiceWorker&&e instanceof ServiceWorker)}export function readTargets(e){const n=new Array,{length:t}=e;for(let o=0;o<t;o+=1){const t=e[o],r=t instanceof HTMLIFrameElement?t.contentWindow:t;r&&n.push(r)}return n}
|
package/imageToBlob.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{get2dContextError}from"./
|
|
1
|
+
import{get2dContextError}from"./takeScreenshot";export function imageToBlob(t){return new Promise((e,o)=>{const r=document.createElement("canvas");r.width=t.width,r.height=t.height;const n=r.getContext("2d");if(!n)throw get2dContextError();n.drawImage(t,0,0),r.toBlob(t=>{t?e(t):o(new Error("Unable to get blob from image."))})})}
|
package/isWebPSupported.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export async function isWebPSupported(A="lossy"){const Q={lossy:"UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",lossless:"UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},o=new Image;return new Promise(
|
|
1
|
+
export async function isWebPSupported(A="lossy"){const Q={lossy:"UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",lossless:"UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",alpha:"UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",animation:"UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"},o=new Image;return new Promise(l=>{o.onload=()=>l(o.width>0&&o.height>0),o.onerror=()=>l(!1),o.src=`data:image/webp;base64,${Q[A]}`})}
|
package/loadImage.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function loadImage(o){return new Promise((
|
|
1
|
+
export function loadImage(o){return new Promise((n,r)=>{const e=new Image;if(e.onload=()=>{e.onload=null,e.onerror=null,n(e)},e.onerror=o=>{e.onload=null,e.onerror=null,r(o)},"string"==typeof o)e.src=o;else{const{crossOrigin:n,...r}=o;void 0!==n&&(e.crossOrigin=n),Object.assign(e,r)}})}
|
package/loadScript.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
export interface LoadScriptOptions extends Partial<Pick<HTMLScriptElement, 'id'
|
|
1
|
+
export interface LoadScriptOptions extends Partial<Pick<HTMLScriptElement, 'id'>> {
|
|
2
|
+
/** Defaults to `true`. */
|
|
3
|
+
async?: boolean | undefined;
|
|
4
|
+
/** Defaults to `false`. */
|
|
5
|
+
defer?: boolean | undefined;
|
|
6
|
+
/** Defaults to `false`. */
|
|
2
7
|
keepScript?: boolean | undefined;
|
|
8
|
+
/** Defaults to `true`. */
|
|
9
|
+
waitDomReady?: boolean | undefined;
|
|
3
10
|
}
|
|
4
|
-
export declare function loadScript(url: string, {
|
|
11
|
+
export declare function loadScript(url: string, { id, keepScript, async, defer, waitDomReady, }?: LoadScriptOptions, isExecuted?: (() => boolean) | undefined): Promise<void>;
|
package/loadScript.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{onDOMReady}from"./onDOMReady";function findScript(e){const
|
|
1
|
+
import{onDOMReady}from"./onDOMReady";function findScript(e){const r=e.startsWith("//")?window.location.protocol+e:e,{length:t}=document.scripts;for(let e=0;e<t;e+=1)if(document.scripts[e].src===r)return document.scripts[e]}function load(e,{id:r,keepScript:t,async:n,defer:o},c,d,i){try{const s=r?document.scripts.namedItem(r):findScript(e);if(s&&(!c||c()))return void d();const a=s??document.createElement("script"),p=()=>{a.removeEventListener("load",m),a.removeEventListener("error",f),t||s||a.remove()},m=()=>{p(),d()},f=r=>{p();const t=r instanceof ErrorEvent?r:new Error(`Unable to load script by url ${e}.`,{cause:r});i(t)};a.addEventListener("load",m,{once:!0}),a.addEventListener("error",f,{once:!0}),s||(r&&(a.id=r),a.async=n,a.defer=o,a.src=e,document.head.appendChild(a))}catch(e){i(e)}}export function loadScript(e,{id:r,keepScript:t=!1,async:n=!0,defer:o=!1,waitDomReady:c=!0}={},d=void 0){return new Promise((i,s)=>{c?onDOMReady(()=>{load(e,{id:r??"",keepScript:t,async:n,defer:o},d,i,s)}):load(e,{id:r??"",keepScript:t,async:n,defer:o},d,i,s)})}
|
package/media/Capabilities.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getMediaSource}from"./getMediaSource";export class Capabilities{static supportMap=new Map;static canPlayMap=new Map;static tmpVideo;static cacheTimer;static isCanPlayType(t){if(this.canPlayMap.has(t))return!!this.canPlayMap.get(t);this.tmpVideo||(this.tmpVideo=document.getElementsByTagName("video")[0]||document.createElement("video"),window.clearTimeout(this.cacheTimer),this.cacheTimer=window.setTimeout((
|
|
1
|
+
import{getMediaSource}from"./getMediaSource";export class Capabilities{static supportMap=new Map;static canPlayMap=new Map;static tmpVideo;static cacheTimer;static isCanPlayType(t){if(this.canPlayMap.has(t))return!!this.canPlayMap.get(t);this.tmpVideo||(this.tmpVideo=document.getElementsByTagName("video")[0]||document.createElement("video"),window.clearTimeout(this.cacheTimer),this.cacheTimer=window.setTimeout(()=>{this.tmpVideo=void 0},1e3));const e=!!this.tmpVideo.canPlayType(t);return this.supportMap.set(t,e),e}static isTypeSupported(t,e){if(this.supportMap.has(t))return!!this.supportMap.get(t);const i=getMediaSource(e);if(i){const e=i.isTypeSupported(t);return this.supportMap.set(t,e),e}return!1}static reset(){window.clearTimeout(this.cacheTimer),this.tmpVideo=void 0,this.supportMap.clear(),this.canPlayMap.clear()}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{resetMedia}from"./resetMedia";export function attachMediaStream(e,t){t&&t.active&&e.muted&&0===t.getVideoTracks().filter(
|
|
1
|
+
import{resetMedia}from"./resetMedia";export function attachMediaStream(e,t){t&&t.active&&e.muted&&0===t.getVideoTracks().filter(e=>!e.getSettings().displaySurface).length?e.srcObject=null:e.srcObject=t&&t.active?t:null}export function removeTrack(e,t){e.removeTrack(t),e.dispatchEvent(new MediaStreamTrackEvent("removetrack",{track:t}))}export function addTrack(e,t,a){e.addTrack(t),e.dispatchEvent(new MediaStreamTrackEvent("addtrack",{track:t})),t.addEventListener("ended",()=>{removeTrack(e,t),a&&a()},{once:!0})}export class MediaStreamController{mediaStream;media;constructor(e){this.mediaStream=e}attach(e){this.media=e,attachMediaStream(e,this.mediaStream)}detach(){if(this.media){const{media:e}=this;this.media=void 0,resetMedia(e)}}updateStream(e){if(this.mediaStream===e)return;const{media:t}=this;this.mediaStream=e,t&&this.attach(t)}removeTrack(e){removeTrack(this.mediaStream,e)}addTrack(e,t){addTrack(this.mediaStream,e,()=>{this.removeTrack(e),t&&t()})}reset(){this.mediaStream.getTracks().forEach(e=>{e.stop(),this.removeTrack(e)})}destroy(){this.detach(),this.reset()}[Symbol.dispose](){this.destroy()}}
|
package/media/PipController.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{EventEmitterListener}from"../EventEmitterListener";import{toggleNativeSubtitles}from"./toggleNativeSubtitles";const getPipUnavailableError=()=>new Error("PiP is not available");export class PipController extends EventEmitter{options;static isApiEnabled(){return!!HTMLVideoElement.prototype.requestPictureInPicture&&!!document.exitPictureInPicture&&!!document.pictureInPictureEnabled}static isWebkitApiEnabled(e){return!!e.webkitSupportsPresentationMode&&e.webkitSupportsPresentationMode("picture-in-picture")}static isAvailable(e){return this.isApiEnabled()&&!e.disablePictureInPicture||this.isWebkitApiEnabled(e)}get Events(){return PipController.Events}listener;constructor(e,t={}){if(super(),this.options=t,this.listener=new EventEmitterListener(e),PipController.isAvailable(e)){const e=(()=>{const e=()=>{e.nativeSubtitles=this.options.toggleNativeSubtitles&&this.listener.target.textTracks.length>0,e.nativeSubtitles&&toggleNativeSubtitles(!0,this.listener.target.textTracks),this.emit(this.Events.Change,{pip:!0})};return e.nativeSubtitles=void 0,e})(),t=()=>{e.nativeSubtitles&&toggleNativeSubtitles(!1,this.listener.target.textTracks),this.emit(this.Events.Change,{pip:!1})};PipController.isApiEnabled()?(this.listener.on("enterpictureinpicture",e),this.listener.on("leavepictureinpicture",t)):this.listener.on("webkitpresentationmodechanged",(()=>{let i=this.listener.target.webkitPresentationMode;return()=>{"picture-in-picture"===this.listener.target.webkitPresentationMode?e():"picture-in-picture"===i&&t(),i=this.listener.target.webkitPresentationMode}})(),!0)}}isPip(){return PipController.isApiEnabled()?document.pictureInPictureElement===this.listener.target:"picture-in-picture"===this.listener.target.webkitPresentationMode}getCurrentElement(){return this.isPip()?this.listener.target:null}request(){return new Promise((
|
|
1
|
+
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{EventEmitterListener}from"../EventEmitterListener";import{toggleNativeSubtitles}from"./toggleNativeSubtitles";const getPipUnavailableError=()=>new Error("PiP is not available");export class PipController extends EventEmitter{options;static isApiEnabled(){return!!HTMLVideoElement.prototype.requestPictureInPicture&&!!document.exitPictureInPicture&&!!document.pictureInPictureEnabled}static isWebkitApiEnabled(e){return!!e.webkitSupportsPresentationMode&&e.webkitSupportsPresentationMode("picture-in-picture")}static isAvailable(e){return this.isApiEnabled()&&!e.disablePictureInPicture||this.isWebkitApiEnabled(e)}get Events(){return PipController.Events}listener;constructor(e,t={}){if(super(),this.options=t,this.listener=new EventEmitterListener(e),PipController.isAvailable(e)){const e=(()=>{const e=()=>{e.nativeSubtitles=this.options.toggleNativeSubtitles&&this.listener.target.textTracks.length>0,e.nativeSubtitles&&toggleNativeSubtitles(!0,this.listener.target.textTracks),this.emit(this.Events.Change,{pip:!0})};return e.nativeSubtitles=void 0,e})(),t=()=>{e.nativeSubtitles&&toggleNativeSubtitles(!1,this.listener.target.textTracks),this.emit(this.Events.Change,{pip:!1})};PipController.isApiEnabled()?(this.listener.on("enterpictureinpicture",e),this.listener.on("leavepictureinpicture",t)):this.listener.on("webkitpresentationmodechanged",(()=>{let i=this.listener.target.webkitPresentationMode;return()=>{"picture-in-picture"===this.listener.target.webkitPresentationMode?e():"picture-in-picture"===i&&t(),i=this.listener.target.webkitPresentationMode}})(),!0)}}isPip(){return PipController.isApiEnabled()?document.pictureInPictureElement===this.listener.target:"picture-in-picture"===this.listener.target.webkitPresentationMode}getCurrentElement(){return this.isPip()?this.listener.target:null}request(){return new Promise((e,t)=>{if(this.isPip())e();else{if(!PipController.isAvailable(this.listener.target))throw getPipUnavailableError();PipController.isApiEnabled()?this.listener.target.requestPictureInPicture().then(()=>e(),t):(this.listener.once("webkitpresentationmodechanged",()=>{"picture-in-picture"===this.listener.target.webkitPresentationMode?e():t(new Error("Something went wrong."))},!0),this.listener.target.webkitSetPresentationMode("picture-in-picture"))}})}exit(){return new Promise((e,t)=>{if(this.isPip()){if(!PipController.isAvailable(this.listener.target))throw getPipUnavailableError();PipController.isApiEnabled()?document.exitPictureInPicture().then(e,t):(this.listener.once("webkitpresentationmodechanged",()=>{"picture-in-picture"!==this.listener.target.webkitPresentationMode?e():t(new Error("Something went wrong."))},!0),this.listener.target.webkitSetPresentationMode("inline"))}else e()})}destroy(){return this.exit().finally(()=>{this.removeAllListeners(),this.listener.removeAllListeners()})}[Symbol.asyncDispose](){return this.destroy()}}!function(e){let t;!function(e){e.Change="change"}(t=e.Events||(e.Events={}))}(PipController||(PipController={}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{EventListeners}from"../../EventListeners";import{MediaNotAttachedError}from"../MediaNotAttachedError";import{parseTextTracks,setActiveTextTrack,addTextTracks,isIOSFullscreen,splitRows,buildCueId}from"./utils";function dispatchNativeEvent(t,e,s){t.dispatchEvent(new CustomEvent(e,{detail:s}))}export class TextTracksController extends EventEmitter{options;eventListeners=new EventListeners;addedTracks=[];textTrackList=[];media;textTrack;nextTextTrack;get Events(){return TextTracksController.Events}constructor(t){super(),this.options={emitNativeEvents:!1,hideActiveTrack:!0,preferCueRowLength:0},t&&this.setOptions(t)}setOptions(t){Object.assign(this.options,{...t,emitNativeEvents:t.emitNativeEvents??this.options.emitNativeEvents,hideActiveTrack:t.hideActiveTrack??this.options.hideActiveTrack,preferCueRowLength:t.preferCueRowLength??this.options.preferCueRowLength})}isAttached(){return!!this.media}getMediaElement(){if(!this.media)throw new MediaNotAttachedError;return this.media}detach(){this.eventListeners.removeAllListeners(),this.media=void 0,this.addedTracks=[],this.textTrackList=[],this.textTrack=void 0,this.nextTextTrack=void 0}attach(t){this.detach();const e=(()=>{const e=[];return s=>{const{activeCues:i}=s.target;if(!i)return;
|
|
1
|
+
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{EventListeners}from"../../EventListeners";import{MediaNotAttachedError}from"../MediaNotAttachedError";import{parseTextTracks,setActiveTextTrack,addTextTracks,isIOSFullscreen,splitRows,buildCueId}from"./utils";function dispatchNativeEvent(t,e,s){t.dispatchEvent(new CustomEvent(e,{detail:s}))}export class TextTracksController extends EventEmitter{options;eventListeners=new EventListeners;addedTracks=[];textTrackList=[];media;textTrack;nextTextTrack;get Events(){return TextTracksController.Events}constructor(t){super(),this.options={emitNativeEvents:!1,hideActiveTrack:!0,preferCueRowLength:0},t&&this.setOptions(t)}setOptions(t){Object.assign(this.options,{...t,emitNativeEvents:t.emitNativeEvents??this.options.emitNativeEvents,hideActiveTrack:t.hideActiveTrack??this.options.hideActiveTrack,preferCueRowLength:t.preferCueRowLength??this.options.preferCueRowLength})}isAttached(){return!!this.media}getMediaElement(){if(!this.media)throw new MediaNotAttachedError;return this.media}detach(){this.eventListeners.removeAllListeners(),this.media=void 0,this.addedTracks=[],this.textTrackList=[],this.textTrack=void 0,this.nextTextTrack=void 0}attach(t){this.detach();const e=(()=>{const e=[];return s=>{const{activeCues:i}=s.target;if(!i)return;const{length:a}=i,{length:r}=e;let n=r!==a;const c=new Array(a);for(let t=0;t<a;t+=1){const s=i[t];s.id=s.id||buildCueId(s,t),s.rows=splitRows(s.text,this.options.preferCueRowLength),c[t]=s,n||e[t]?.id===s.id||(n=!0),e[t]=s}r>a&&e.splice(a-r),n&&(this.emit(this.Events.TextTrackCueChanged,{textTrack:s.target,cues:c}),this.options.emitNativeEvents&&dispatchNativeEvent(t,"texttrackcuechange",{textTrack:s.target,cues:c}))}})(),s=()=>{this.textTrackList=parseTextTracks(t),this.emit(this.Events.TextTrackListChanged,{textTracks:this.textTrackList}),this.options.emitNativeEvents&&dispatchNativeEvent(t,"texttracklistchange",{textTracks:this.textTrackList}),setActiveTextTrack(t,this.textTrack??this.nextTextTrack,this.options.hideActiveTrack&&!isIOSFullscreen(t))};this.media=t;let i=!1;const a=t=>{i||s(),this.eventListeners.scope(t).on("cuechange",e)},r=t=>{s(),this.eventListeners.scope(t).off("cuechange",e)};if(this.eventListeners.scope(this.media.textTracks).on("change",()=>{const{textTracks:e}=t,{nextTextTrack:s}=this;let i=-1;const{length:a}=e;for(let r=0;r<a;r+=1){const a=e[r];if(a.language===s?.language&&a.kind===s?.kind||isIOSFullscreen(t)||(a.mode="disabled"),"disabled"!==a.mode&&i>=0&&(a.mode="disabled"),"disabled"!==a.mode){if(i=r,!a.native&&!isIOSFullscreen(t)){const t=this.options.hideActiveTrack?"hidden":"showing";a.mode!==t&&(a.mode=t)}a.native&&a.language===s?.language&&a.kind===s.kind&&(a.mode="showing")}}const r=e[i]&&((this.textTrackList[i]&&{...this.textTrackList[i],mode:e[i].mode})??{id:e[i].id,kind:e[i].kind,language:e[i].language,label:e[i].label,mode:e[i].mode});this.textTrack?.language===r?.language&&this.textTrack?.kind===r?.kind&&this.textTrack?.mode===r?.mode||(this.textTrack=r,this.nextTextTrack=this.textTrack,this.emit(this.Events.CurrentTextTrackChanged,{textTrack:this.textTrack,index:i}),this.options.emitNativeEvents&&dispatchNativeEvent(t,"texttrackchange",{textTrack:this.textTrack,index:i}))}).on("addtrack",({track:t})=>t&&a(t)).on("removetrack",({track:t})=>t&&r(t)),this.media.textTracks.length>0){this.textTrackList=parseTextTracks(t),i=!0;try{Array.prototype.forEach.call(this.media.textTracks,a),s()}finally{i=!1}}}getTextTracks(){return this.textTrackList}setTextTracks(t){const e=this.getMediaElement();if(this.eventListeners.scope(e,"@@setTextTracks").removeAllListeners(),this.addedTracks.forEach(t=>t.remove()),0===t.length)return;const s=()=>{addTextTracks(e,t,t=>this.addedTracks.push(t)),this.textTrackList=parseTextTracks(e)};e.readyState>=e.HAVE_CURRENT_DATA?s():this.eventListeners.scope(e,"@@setTextTracks").once("loadeddata",s)}getActiveTextTrack(){return this.textTrack}setActiveTextTrack(t){const e=this.getMediaElement();return this.nextTextTrack=t&&this.textTrackList.find(e=>e.language===t.language&&(!t.kind||e.kind===t.kind)),setActiveTextTrack(e,this.nextTextTrack,this.options.hideActiveTrack&&!isIOSFullscreen(e))}destroy(){this.detach(),this.removeAllListeners()}[Symbol.dispose](){this.destroy()}}!function(t){let e;!function(t){t.TextTrackListChanged="TrackListChanged",t.CurrentTextTrackChanged="CurrentTextTrackChanged",t.TextTrackCueChanged="TextTrackCueChanged"}(e=t.Events||(t.Events={}))}(TextTracksController||(TextTracksController={}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isIOS}from"../../platform/isIOS";const DETACHED_GROUP_ID="__detached__";export function fakeDetachTextTracks(t){Array.prototype.forEach.call(t.textTracks,
|
|
1
|
+
import{isIOS}from"../../platform/isIOS";const DETACHED_GROUP_ID="__detached__";export function fakeDetachTextTracks(t){Array.prototype.forEach.call(t.textTracks,t=>{const e=t;e.customGroupId&&(e.customGroupId="__detached__")})}export function parseTextTracks(t){return 0===t.textTracks.length?[]:Array.prototype.reduce.call(t.textTracks,(t,{customGroupId:e,id:n,kind:r,language:l,label:a})=>("__detached__"!==e&&l&&t.push({id:n,kind:r,language:l,label:a??""}),t),[])}export function isIOSFullscreen(t){return isIOS()&&!!t.webkitDisplayingFullscreen}export function findTextTrack(t,e){return Array.prototype.find.call(t.textTracks,({mode:t,language:n})=>e.some(e=>!(null!=e.mode&&e.mode!==t||null!=e.language&&e.language!==n)))}export function setActiveTextTrack(t,e,n){const{textTracks:r}=t,{length:l}=r;if(0===l)return!1;let a=!1,o=!1;for(let t=0;t<l;t+=1){const l=r[t];if(o||l.language!==e?.language||e.kind&&l.kind!==e.kind)"disabled"!==l.mode&&(l.mode="disabled",a=!0);else{const t=n?"hidden":"showing";l.mode=t,o=!0,a=!0}}return a}export function addTextTracks(t,e,n){const r=new Set;for(const{language:e,kind:n}of t.textTracks)r.add(`${e} ${n}`);e.forEach(e=>{const l=e.kind??"subtitles";if(!r.has(`${e.language} ${l}`)){const r=document.createElement("track");r.src=e.src,r.srclang=e.language,r.label=e.label,r.kind=l,r.default=!1,n(t.appendChild(r))}})}export function buildCueId(t,e){return`${t.startTime}-${e}`}export function splitRows(t,e){if(e<=0)return t.split(/\r?\n/);const n=[];let r=0,l=r,a="";const{length:o}=t;for(let c=0;c<=o;c+=1){const o=t[c];a.length>0&&r<l&&(n[l]=null==o?a.trim():a.trimStart(),a=""),r=l;let i=n[r]??"";if("\n"===o||"\r\n"===o)a.length>0&&i.length+a.length<=e&&(i+=i.length>0?a:a.trimStart(),a=""),l+=1;else if(" "===o){if(a.length>0){i.length+a.length>e&&i.length>0?(l+=1,i=i.trimEnd()):(i+=0===i.length?a.trimStart():a,a="")}a+=o}else if(null==o&&a.length>0){i.length+a.length>e&&0!==i.length?(r+=1,i=a.trim()):i+=a}else o&&(a+=o);n[r]=i}return n}
|
package/media/parseCueText.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{splitRows}from"./TextTracksController/utils";const ESCAPE={"&":"&","<":"<",">":">","‎":"","‏":""," ":" "},TAG_NAME={c:"span",i:"i",b:"b",u:"u",ruby:"ruby",rt:"rt",lang:"span"},TAG_ANNOTATION={v:"title",lang:"lang"},NEEDS_PARENT={rt:"ruby"};function computeSeconds(e,t,n,o){return 3600*(+e||0)+60*(+t||0)+(+n||0)+(+o||0)/1e3}function parseTimeStamp(e){const t=e.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);if(!t)return;const[,n,o,r,l]=t;return l?computeSeconds(n,o,r.replace(":",""),l):+n>59?computeSeconds(n,o,"",l):computeSeconds("",n,o,l)}function unescape(e){let t,n=e;for(;t=n.match(/&(amp|lt|gt|lrm|rlm|nbsp);/);)n=n.replace(t[0],
|
|
1
|
+
import{splitRows}from"./TextTracksController/utils";const ESCAPE={"&":"&","<":"<",">":">","‎":"","‏":""," ":" "},TAG_NAME={c:"span",i:"i",b:"b",u:"u",ruby:"ruby",rt:"rt",lang:"span"},TAG_ANNOTATION={v:"title",lang:"lang"},NEEDS_PARENT={rt:"ruby"};function computeSeconds(e,t,n,o){return 3600*(+e||0)+60*(+t||0)+(+n||0)+(+o||0)/1e3}function parseTimeStamp(e){const t=e.match(/^(\d+):(\d{2})(:\d{2})?\.(\d{3})/);if(!t)return;const[,n,o,r,l]=t;return l?computeSeconds(n,o,r.replace(":",""),l):+n>59?computeSeconds(n,o,"",l):computeSeconds("",n,o,l)}function unescape(e){let t,n=e;for(;t=n.match(/&(amp|lt|gt|lrm|rlm|nbsp);/);)n=n.replace(t[0],e=>ESCAPE[e]);return n}function nextToken(e){if(!e)return[e,void 0];const t=e.match(/^([^<]*)(<[^>]*>?)?/);if(!t)return[e,void 0];const n=t[1]?t[1]:t[2];return null==n?[e,n]:[e.substring(n.length),n]}function shouldAdd(e,t){return!NEEDS_PARENT[t.localName]||NEEDS_PARENT[t.localName]===e.localName}function createHtmlNode(e,t){const n=TAG_NAME[e];if(!n)return;const o=window.document.createElement(n),r=TAG_ANNOTATION[e];return r&&t&&(o[r]=t.trim()),o}export function parseCueText(e,t,{preferLineLength:n=0}={}){let o,r,l,s=e,c=-1;const a=[],u=[],i=[],d=e=>{0===u.length&&u.push([]),u.at(-1).push(t?t(e,(u.at(-1)??u.at(-2))?.at(-1)):e)},p=e=>{const t=a.pop()??"",n=o;if(o=n.parentElement||void 0,null==o){d({id:e,startTime:c>=0?c:void 0,tag:t,node:n}),r=n}},m=()=>`${u.length}-${(u.at(-1)?.length??0)+1}`,h=(e,t)=>{t?i.push(e):i[i.length-1]+=e,t&&u.push([]),null==o?0===e.trim().length&&!t&&r?r.appendChild(window.document.createTextNode(unescape(e))):(e=>{const t=createHtmlNode("c","");t.appendChild(window.document.createTextNode(unescape(e)));const n={id:m(),node:t,tag:"c",startTime:c>=0?c:void 0};d(n)})(e):o.appendChild(window.document.createTextNode(unescape(e)))};for(;null!=([s,l]=nextToken(s),l);)if("<"===l[0])if("/"===l[1])a.at(-1)===l.substring(2).replace(">","")&&p(m());else{const e=parseTimeStamp(l.substring(1,l.length-1));if(e)c=e;else{const e=l.match(/^<([^.\s/0-9>]+)(\.[^\s\\>]+)?([^>\\]+)?(\\?)>?$/),t=e&&createHtmlNode(e[1],e[3]);!t||o&&!shouldAdd(o,t)||(e[2]&&(t.className=e[2].substring(1).replace("."," ")),a.push(e[1]),o?.appendChild(t),o=t)}}else if(0===i.length||n>0&&i.at(-1).length+l.length>n){const e=splitRows(l,n),{length:t}=e;for(let n=0;n<t;n+=1)h(e[n],!0)}else h(l,!1);return{segments:u,rawText:i}}
|
package/media/resetMedia.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function resetMedia(e){(e.src||e.srcObject||e.childElementCount>0)&&(URL.revokeObjectURL(e.src),e.removeAttribute("src"),e.srcObject=null,e.childElementCount>0&&Array.prototype.filter.call(e.children,
|
|
1
|
+
export function resetMedia(e){(e.src||e.srcObject||e.childElementCount>0)&&(URL.revokeObjectURL(e.src),e.removeAttribute("src"),e.srcObject=null,e.childElementCount>0&&Array.prototype.filter.call(e.children,e=>e instanceof HTMLSourceElement).forEach(r=>{URL.revokeObjectURL(r.src),e.removeChild(r)}),e.load())}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export function toggleNativeSubtitles(e,t){for(let
|
|
1
|
+
export function toggleNativeSubtitles(e,t){const{length:o}=t;for(let n=0;n<o;n+=1){const o=t[n];e?o.native=!0:delete o.native,e&&"hidden"===o.mode?o.mode="showing":e||"showing"!==o.mode||(o.mode="hidden")}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@js-toolkit/web-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.65.0",
|
|
4
4
|
"description": "Web utils",
|
|
5
5
|
"author": "VZH",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,33 +17,33 @@
|
|
|
17
17
|
"minor-publish": "npm run build && npm version minor --force --no-workspaces-update -m 'v%s' && npm run copy:configs && cd ./dist && npm publish --access public && git push --follow-tags"
|
|
18
18
|
},
|
|
19
19
|
"optionalDependencies": {
|
|
20
|
-
"@js-toolkit/node-utils": "^1.2.
|
|
20
|
+
"@js-toolkit/node-utils": "^1.2.6"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@eslint/compat": "^1.2
|
|
23
|
+
"@eslint/compat": "^1.3.2",
|
|
24
24
|
"@eslint/eslintrc": "^3.3.1",
|
|
25
|
-
"@eslint/js": "^9.
|
|
26
|
-
"@js-toolkit/configs": "^3.
|
|
27
|
-
"@js-toolkit/utils": "^1.
|
|
25
|
+
"@eslint/js": "^9.33.0",
|
|
26
|
+
"@js-toolkit/configs": "^3.95.1",
|
|
27
|
+
"@js-toolkit/utils": "^1.60.1",
|
|
28
28
|
"@types/eslint": "^9.6.1",
|
|
29
29
|
"@types/lodash.throttle": "^4.1.9",
|
|
30
30
|
"@types/uuid": "^10.0.0",
|
|
31
31
|
"copyfiles": "^2.4.1",
|
|
32
|
-
"eslint": "^9.
|
|
33
|
-
"eslint-config-prettier": "^10.1.
|
|
34
|
-
"eslint-import-resolver-typescript": "^4.
|
|
35
|
-
"eslint-plugin-import": "^2.
|
|
36
|
-
"eslint-plugin-prettier": "^5.4
|
|
32
|
+
"eslint": "^9.33.0",
|
|
33
|
+
"eslint-config-prettier": "^10.1.8",
|
|
34
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
35
|
+
"eslint-plugin-import": "^2.32.0",
|
|
36
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
37
37
|
"lodash.throttle": "^4.1.1",
|
|
38
|
-
"prettier": "^3.
|
|
38
|
+
"prettier": "^3.6.2",
|
|
39
39
|
"reconnecting-websocket": "^4.4.0",
|
|
40
40
|
"rimraf": "^6.0.1",
|
|
41
|
-
"terser": "^5.
|
|
42
|
-
"typescript": "^5.
|
|
43
|
-
"typescript-eslint": "^8.
|
|
44
|
-
"ua-parser-js": "^2.0.
|
|
41
|
+
"terser": "^5.43.1",
|
|
42
|
+
"typescript": "^5.9.2",
|
|
43
|
+
"typescript-eslint": "^8.40.0",
|
|
44
|
+
"ua-parser-js": "^2.0.4",
|
|
45
45
|
"uuid": "^11.1.0",
|
|
46
|
-
"webpack": "^5.
|
|
47
|
-
"yargs": "^
|
|
46
|
+
"webpack": "^5.101.3",
|
|
47
|
+
"yargs": "^18.0.0"
|
|
48
48
|
}
|
|
49
49
|
}
|
package/patchConsoleLogging.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const methods={debug:console.debug.bind(console),error:console.error.bind(console),info:console.info.bind(console),log:console.log.bind(console),trace:console.trace.bind(console),warn:console.warn.bind(console)};export function restoreConsoleLogging(){Object.entries(methods).forEach((
|
|
1
|
+
const methods={debug:console.debug.bind(console),error:console.error.bind(console),info:console.info.bind(console),log:console.log.bind(console),trace:console.trace.bind(console),warn:console.warn.bind(console)};export function restoreConsoleLogging(){Object.entries(methods).forEach(([o,e])=>{console[o]=e})}export function patchConsoleLogging(o,{mode:e="replace"}={}){restoreConsoleLogging(),Object.getOwnPropertyNames(methods).forEach(n=>{const s=n;console[s]=(...n)=>{"append"===e&&methods[s](...n),o(s,...n),"prepend"===e&&methods[s](...n)}})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{onPageReady}from"../onPageReady";export function getNavigationTiming(){return new Promise(
|
|
1
|
+
import{onPageReady}from"../onPageReady";export function getNavigationTiming(){return new Promise(e=>{onPageReady(()=>setTimeout(()=>{try{const n=window.performance?.getEntriesByType("navigation")[0];e(n)}catch{e(void 0)}},0))})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{UAParser}from"ua-parser-js";let syncResult,asyncResult,promise;function toPlatformInfo(t){return{...t,toStringObject(){return Object.getOwnPropertyNames(this).reduce((
|
|
1
|
+
import{UAParser}from"ua-parser-js";let syncResult,asyncResult,promise;function toPlatformInfo(t){return{...t,toStringObject(){return Object.getOwnPropertyNames(this).reduce((t,e)=>{const n=e;return null!=this[n]&&"function"!=typeof this[n]&&(t[n]=this[n].toString()),t},{})}}}export function getPlatformInfoSync(){return null==syncResult&&(syncResult=toPlatformInfo(new UAParser(navigator.userAgent).getResult().withFeatureCheck())),syncResult}export async function getPlatformInfo(){return null==asyncResult&&(promise=promise??Promise.resolve(new UAParser(navigator.userAgent).getResult().withFeatureCheck().withClientHints()),asyncResult=toPlatformInfo(await promise),syncResult=asyncResult,promise=void 0),asyncResult}export function getCachedPlatformInfo(){return null==asyncResult&&(console.warn("PlatformInfo is not ready yet."),getPlatformInfo()),asyncResult}
|
package/rafCallback.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function rafCallback(n){let a=0;const e=(...e)=>{a=requestAnimationFrame((
|
|
1
|
+
export function rafCallback(n){let a=0;const e=(...e)=>{a=requestAnimationFrame(()=>n(...e))};return e.cancel=()=>cancelAnimationFrame(a),e}
|
package/saveFileAs.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function saveFileAs(t,e,r){const n=document.createElement("a");n.setAttribute("href",e),n.setAttribute("download",t),n.setAttribute("type","attachment"),r&&Object.entries(r).forEach((
|
|
1
|
+
export function saveFileAs(t,e,r){const n=document.createElement("a");n.setAttribute("href",e),n.setAttribute("download",t),n.setAttribute("type","attachment"),r&&Object.entries(r).forEach(([t,e])=>{n.setAttribute(t,e),"target"===t&&"_blank"===e&&null==r.rel&&n.setAttribute("rel","noopener noreferrer")}),n.click()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{ErrorCompat}from"@js-toolkit/utils/ErrorCompat";import{onPageReady}from"../onPageReady";import{isLocalhost}from"./utils";export class ServiceWorkerUnavailableError extends ErrorCompat{constructor(){super(ServiceWorkerUnavailableError,"ServiceWorker is not available",{name:"ServiceWorkerUnavailableError"})}}export class ServiceWorkerInstaller extends EventEmitter{static isAvailable(){return"serviceWorker"in navigator}registration;cancelDefferedRegister;constructor(){super()}register(r,e){if(!ServiceWorkerInstaller.isAvailable())throw new ServiceWorkerUnavailableError;const{deffered:t,...i}=e??{},o=async()=>{try{if(isLocalhost()){const e=await fetch(r);if(!e.ok)throw new Error(`No service worker found at '${e.url}'.`,{cause:`Response: ${e.status} ${e.statusText}`})}const e=await navigator.serviceWorker.register(r,i);this.registration=e,this.emit("registered",{registration:e}),e.onupdatefound=()=>{const r=e.installing;null!=r&&(r.onstatechange=()=>{"installed"===r.state&&(navigator.serviceWorker.controller?this.emit("updatePending",{registration:e}):this.emit("updated",{registration:e}))},r.onerror=r=>{const e=new Error("Error during service worker installation",{cause:r});this.emit("error",{error:e})})}}catch(r){const e=new Error("Error during service worker registration",{cause:r});this.emit("error",{error:e})}};t?this.cancelDefferedRegister=onPageReady(o,"number"==typeof t?{timeout:t}:void 0):o()}unregister(){this.cancelDefferedRegister&&this.cancelDefferedRegister(),this.registration?.unregister().catch(
|
|
1
|
+
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{ErrorCompat}from"@js-toolkit/utils/ErrorCompat";import{onPageReady}from"../onPageReady";import{isLocalhost}from"./utils";export class ServiceWorkerUnavailableError extends ErrorCompat{constructor(){super(ServiceWorkerUnavailableError,"ServiceWorker is not available",{name:"ServiceWorkerUnavailableError"})}}export class ServiceWorkerInstaller extends EventEmitter{static isAvailable(){return"serviceWorker"in navigator}registration;cancelDefferedRegister;constructor(){super()}register(r,e){if(!ServiceWorkerInstaller.isAvailable())throw new ServiceWorkerUnavailableError;const{deffered:t,...i}=e??{},o=async()=>{try{if(isLocalhost()){const e=await fetch(r);if(!e.ok)throw new Error(`No service worker found at '${e.url}'.`,{cause:`Response: ${e.status} ${e.statusText}`})}const e=await navigator.serviceWorker.register(r,i);this.registration=e,this.emit("registered",{registration:e}),e.onupdatefound=()=>{const r=e.installing;null!=r&&(r.onstatechange=()=>{"installed"===r.state&&(navigator.serviceWorker.controller?this.emit("updatePending",{registration:e}):this.emit("updated",{registration:e}))},r.onerror=r=>{const e=new Error("Error during service worker installation",{cause:r});this.emit("error",{error:e})})}}catch(r){const e=new Error("Error during service worker registration",{cause:r});this.emit("error",{error:e})}};t?this.cancelDefferedRegister=onPageReady(o,"number"==typeof t?{timeout:t}:void 0):o()}unregister(){this.cancelDefferedRegister&&this.cancelDefferedRegister(),this.registration?.unregister().catch(r=>{const e=new Error("Error during service worker unregister",{cause:r});this.emit("error",{error:e})})}destroy(){this.cancelDefferedRegister&&this.cancelDefferedRegister(),this.removeAllListeners()}[Symbol.dispose](){this.destroy()}}
|
package/serviceWorker/utils.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getErrorMessage}from"@js-toolkit/utils/getErrorMessage";export function isLocalhost(e=window.location.hostname){return!("localhost"!==e&&"[::1]"!==e&&!e.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/))}export function removeUnknownCaches(e){return caches.keys().then(
|
|
1
|
+
import{getErrorMessage}from"@js-toolkit/utils/getErrorMessage";export function isLocalhost(e=window.location.hostname){return!("localhost"!==e&&"[::1]"!==e&&!e.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/))}export function removeUnknownCaches(e){return caches.keys().then(r=>{const o=new Set(Object.values(e));return Promise.all(r.map(e=>{if(!o.has(e))return caches.delete(e)}))})}export async function addResourcesToCache(e,r){const o=await caches.open(e);await o.addAll(r)}export async function cacheFirst(e,{request:r,fallbackUrl:o,saveToCache:t,logger:n=console}){const s=await caches.open(e),c=await s.match(r);if(c)return n.debug("Found response in cache:",c),c;n.debug("No response for %s found in cache. About to fetch from network...",r.url);try{const e=await fetch(r.clone());return n.debug("Response for %s from network is: %O",r.url,e),e.status<400&&(!t||t({request:r,response:e}))?(n.debug("Caching the response to",r.url),s.put(r,e.clone()).catch(e=>{n.error(getErrorMessage(new Error(`Caching error of ${r.url}`,{cause:e})))})):n.debug("Not caching the response to",r.url),e}catch(e){const r=o&&await s.match(o);if(r)return r;throw n.error("Error in fetch handler:",e),e}}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function get2dContextError(): Error;
|
|
2
|
+
export interface TakeScreenshotOptions {
|
|
3
|
+
width?: number | undefined;
|
|
4
|
+
height?: number | undefined;
|
|
5
|
+
type?: string | undefined;
|
|
6
|
+
quality?: number | undefined;
|
|
7
|
+
}
|
|
8
|
+
export declare function takeScreenshot(element: CanvasImageSource, { width, height, type, quality, }?: TakeScreenshotOptions): string;
|
|
9
|
+
export declare function takeScreenshotAsync(element: CanvasImageSource, { width, height, type, quality, }?: TakeScreenshotOptions): Promise<Blob>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{hasIn}from"@js-toolkit/utils/hasIn";export function get2dContextError(){return new Error("Failed to get canvas 2d context.")}const getDefaultWidth=t=>t instanceof HTMLVideoElement?t.videoWidth:hasIn(t,"displayWidth")?t.displayWidth:t.width instanceof SVGAnimatedLength?t.width.animVal.value:t.width,getDefaultHeight=t=>t instanceof HTMLVideoElement?t.videoHeight:hasIn(t,"displayHeight")?t.displayHeight:t.height instanceof SVGAnimatedLength?t.height.animVal.value:t.height;export function takeScreenshot(t,{width:e=getDefaultWidth(t),height:i=getDefaultHeight(t),type:n="image/jpeg",quality:a=1}={}){const o=document.createElement("canvas");o.width=e,o.height=i;const h=o.getContext("2d");if(!h)throw get2dContextError();return h.drawImage(t,0,0),o.toDataURL(n,a)}export function takeScreenshotAsync(t,{width:e=getDefaultWidth(t),height:i=getDefaultHeight(t),type:n="image/jpeg",quality:a=1}={}){return new Promise((o,h)=>{const r=document.createElement("canvas");r.width=e,r.height=i;const d=r.getContext("2d");if(!d)throw get2dContextError();d.drawImage(t,0,0),r.toBlob(t=>{null==t?h(new Error("Unable get blob")):o(t)},n,a)})}
|
package/toBase64.d.ts
CHANGED
package/toBase64.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function toBase64(
|
|
1
|
+
export function toBase64(o){const n=window.TextEncoder?Array.from((new TextEncoder).encode(o),o=>String.fromCodePoint(o)).join(""):unescape(encodeURIComponent(o));return window.btoa(n)}
|
package/webrtc/PeerConnection.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{getErrorMessage}from"@js-toolkit/utils/getErrorMessage";import{hasIn}from"@js-toolkit/utils/hasIn";import log from"@js-toolkit/utils/log";import*as sdpUtils from"./sdputils";export class PeerConnection extends EventEmitter{options;get Events(){return PeerConnection.Events}logger;pc;constructor(e={}){super(),this.options=e,this.logger=e.logger??log.getLogger("PeerConnection"),this.pc=this.createPC()}clear(){this.pc.onsignalingstatechange=null,this.pc.onconnectionstatechange=null,this.pc.oniceconnectionstatechange=null,this.pc.ontrack=null,this.pc.onnegotiationneeded=null,this.pc.onicecandidate=null,this.pc.onicecandidateerror=null}createPC(){const e=new RTCPeerConnection(this.options.rtc);e.onsignalingstatechange=()=>{this.logger.debug(`Signaling state changed to: ${e.signalingState}`),"closed"===e.signalingState&&(this.emit(this.Events.Closed),this.clear())};const t=e=>{this.logger.debug(`Connection state changed to: ${e}`),"connected"===e?this.emit(this.Events.Connected):"disconnected"===e&&this.emit(this.Events.Disconnected)};return hasIn(RTCPeerConnection.prototype,"onconnectionstatechange")?e.onconnectionstatechange=()=>t(e.connectionState):e.oniceconnectionstatechange=()=>t(e.iceConnectionState),e.ontrack=({streams:e,track:t})=>{if(this.logger.debug("Remote stream received.",e.length,t.kind),0===e.length)return;const[n]=e;n.onremovetrack=()=>{this.logger.debug("onremovetrack"),this.emit(this.Events.RemoteStreamChanged,n)},n.onaddtrack=()=>{this.logger.debug("onaddtrack"),this.emit(this.Events.RemoteStreamChanged,n)},this.emit(this.Events.RemoteStreamChanged,n)},e.onnegotiationneeded=()=>{const{iceConnectionState:t}=e;"connected"!==t&&"completed"!==t||(this.logger.debug("Reinitializing connection..."),this.emit(this.Events.ReinitializingConnectionRequired))},e.onicecandidate=({candidate:e})=>{e?sdpUtils.isValidIceCandidate(e)&&this.emit(this.Events.LocalIceCandidate,e):this.emit(this.Events.EndOfIceCandidates)},e.onicecandidateerror=e=>{if(e instanceof RTCPeerConnectionIceErrorEvent){const{errorCode:t,errorText:n,hostCandidate:i,url:o}=e;this.logger.warn(`ICE candidate error: errorCode=${t}, errorText=${n}, hostCandidate=${i}, url=${o}`)}else this.logger.warn(`ICE candidate error: ${getErrorMessage(e)}`)},e}async setLocalDescription(e,t){const n=sdpUtils.prepareLocalDescription(t,this.options.codecs);return await e.setLocalDescription(n),n}async setRemoteDescription(e,t){const n=sdpUtils.prepareRemoteDescription(t,this.options.codecs);return await e.setRemoteDescription(n),n}isConnected(){return"connected"===this.pc.iceConnectionState||"completed"===this.pc.iceConnectionState}isClosed(){return"closed"===this.pc.signalingState}addIceCandidate(e){return this.pc.addIceCandidate(e)}attachStream(e){const t=this.pc.getSenders(),n=t.length?e.getTracks().filter(
|
|
1
|
+
import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{getErrorMessage}from"@js-toolkit/utils/getErrorMessage";import{hasIn}from"@js-toolkit/utils/hasIn";import log from"@js-toolkit/utils/log";import*as sdpUtils from"./sdputils";export class PeerConnection extends EventEmitter{options;get Events(){return PeerConnection.Events}logger;pc;constructor(e={}){super(),this.options=e,this.logger=e.logger??log.getLogger("PeerConnection"),this.pc=this.createPC()}clear(){this.pc.onsignalingstatechange=null,this.pc.onconnectionstatechange=null,this.pc.oniceconnectionstatechange=null,this.pc.ontrack=null,this.pc.onnegotiationneeded=null,this.pc.onicecandidate=null,this.pc.onicecandidateerror=null}createPC(){const e=new RTCPeerConnection(this.options.rtc);e.onsignalingstatechange=()=>{this.logger.debug(`Signaling state changed to: ${e.signalingState}`),"closed"===e.signalingState&&(this.emit(this.Events.Closed),this.clear())};const t=e=>{this.logger.debug(`Connection state changed to: ${e}`),"connected"===e?this.emit(this.Events.Connected):"disconnected"===e&&this.emit(this.Events.Disconnected)};return hasIn(RTCPeerConnection.prototype,"onconnectionstatechange")?e.onconnectionstatechange=()=>t(e.connectionState):e.oniceconnectionstatechange=()=>t(e.iceConnectionState),e.ontrack=({streams:e,track:t})=>{if(this.logger.debug("Remote stream received.",e.length,t.kind),0===e.length)return;const[n]=e;n.onremovetrack=()=>{this.logger.debug("onremovetrack"),this.emit(this.Events.RemoteStreamChanged,n)},n.onaddtrack=()=>{this.logger.debug("onaddtrack"),this.emit(this.Events.RemoteStreamChanged,n)},this.emit(this.Events.RemoteStreamChanged,n)},e.onnegotiationneeded=()=>{const{iceConnectionState:t}=e;"connected"!==t&&"completed"!==t||(this.logger.debug("Reinitializing connection..."),this.emit(this.Events.ReinitializingConnectionRequired))},e.onicecandidate=({candidate:e})=>{e?sdpUtils.isValidIceCandidate(e)&&this.emit(this.Events.LocalIceCandidate,e):this.emit(this.Events.EndOfIceCandidates)},e.onicecandidateerror=e=>{if(e instanceof RTCPeerConnectionIceErrorEvent){const{errorCode:t,errorText:n,hostCandidate:i,url:o}=e;this.logger.warn(`ICE candidate error: errorCode=${t}, errorText=${n}, hostCandidate=${i}, url=${o}`)}else this.logger.warn(`ICE candidate error: ${getErrorMessage(e)}`)},e}async setLocalDescription(e,t){const n=sdpUtils.prepareLocalDescription(t,this.options.codecs);return await e.setLocalDescription(n),n}async setRemoteDescription(e,t){const n=sdpUtils.prepareRemoteDescription(t,this.options.codecs);return await e.setRemoteDescription(n),n}isConnected(){return"connected"===this.pc.iceConnectionState||"completed"===this.pc.iceConnectionState}isClosed(){return"closed"===this.pc.signalingState}addIceCandidate(e){return this.pc.addIceCandidate(e)}attachStream(e){const t=this.pc.getSenders(),n=t.length?e.getTracks().filter(e=>!t.find(({track:t})=>!!t&&t.id===e.id)):e.getTracks();n.length?(n.forEach(t=>this.pc.addTrack(t,e)),this.logger.debug(`Attached ${n.length} track(s) to a peer connection.`)):this.logger.debug("No tracks to attach to a peer connection.")}reattachStream(e){const t=this.pc.iceConnectionState;if("new"!==t&&"connected"!==t&&"completed"!==t)return;const n=e?e.getTracks():[];this.pc.getSenders().forEach(e=>{const{track:t}=e;!t||"ended"!==t.readyState&&n.find(e=>e.id===t.id)||(this.pc.removeTrack(e),this.logger.debug(`'${t&&t.kind}' track is removed from a peer connection.`))}),e&&this.attachStream(e)}async createOffer(){const e=await this.pc.createOffer(this.options.offerOptions);return this.setLocalDescription(this.pc,e)}async createAnswer(e){await this.setRemoteDescription(this.pc,e);const t=await this.pc.createAnswer(this.options.offerOptions);return this.setLocalDescription(this.pc,t)}applyAnswer(e){return this.setRemoteDescription(this.pc,e)}reconnect(){this.close(),this.pc=this.createPC()}close(){this.pc.close(),this.pc.onsignalingstatechange&&(this.emit(this.Events.Closed),this.clear())}destroy(){this.close(),this.removeAllListeners()}[Symbol.dispose](){this.destroy()}}!function(e){let t;!function(e){e.LocalIceCandidate="LocalIceCandidate",e.EndOfIceCandidates="EndOfIceCandidates",e.Connected="Connected",e.Disconnected="Disconnected",e.RemoteStreamChanged="RemoteStreamChanged",e.ReinitializingConnectionRequired="ReinitializingConnectionRequired",e.Closed="Closed"}(t=e.Events||(e.Events={}))}(PeerConnection||(PeerConnection={}));
|
package/webrtc/sdputils.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function trace(e){if(e.endsWith("\n")&&(e=e.substring(0,e.length-1)),window.performance){const t=(window.performance.now()/1e3).toFixed(3);console.log(`${t}: ${e}`)}else console.log(e)}function iceCandidateType(e){return e.split(" ")[7]}export function isValidIceCandidate({candidate:e},t){return!(!e||e.includes("tcp"))&&(!t||"relay"!==t.iceTransportPolicy||"relay"===iceCandidateType(e))}function maybeSetOpusOptions(e,t){return"true"===t.opusStereo?e=setCodecParam(e,"opus/48000","stereo","1"):"false"===t.opusStereo&&(e=removeCodecParam(e,"opus/48000","stereo")),"true"===t.opusFec?e=setCodecParam(e,"opus/48000","useinbandfec","1"):"false"===t.opusFec&&(e=removeCodecParam(e,"opus/48000","useinbandfec")),"true"===t.opusDtx?e=setCodecParam(e,"opus/48000","usedtx","1"):"false"===t.opusDtx&&(e=removeCodecParam(e,"opus/48000","usedtx")),t.opusMaxPbr&&(e=setCodecParam(e,"opus/48000","maxplaybackrate",t.opusMaxPbr)),e}function maybeSetAudioSendBitRate(e,t){return t.audioSendBitrate?(trace(`Prefer audio send bitrate: ${t.audioSendBitrate}`),preferBitRate(e,t.audioSendBitrate,"audio")):e}function maybeSetAudioReceiveBitRate(e,t){return t.audioRecvBitrate?(trace(`Prefer audio receive bitrate: ${t.audioRecvBitrate}`),preferBitRate(e,t.audioRecvBitrate,"audio")):e}function maybeSetVideoSendBitRate(e,t){return t.videoSendBitrate?(trace(`Prefer video send bitrate: ${t.videoSendBitrate}`),preferBitRate(e,t.videoSendBitrate,"video")):e}function maybeSetVideoReceiveBitRate(e,t){return t.videoRecvBitrate?(trace(`Prefer video receive bitrate: ${t.videoRecvBitrate}`),preferBitRate(e,t.videoRecvBitrate,"video")):e}function preferBitRate(e,t,n){const i=e.split("\r\n"),o=findLine(i,"m=",n);if(-1===o)return trace("Failed to add bandwidth line to sdp, as no m-line found"),e;let r=findLineInRange(i,o+1,-1,"m=");-1===r&&(r=i.length);const a=findLineInRange(i,o+1,r,"c=");if(-1===a)return trace("Failed to add bandwidth line to sdp, as no c-line found"),e;const d=findLineInRange(i,a+1,r,"b=AS");d>=0&&i.splice(d,1);const c=`b=AS:${t}`;return i.splice(a+1,0,c),e=i.join("\r\n")}function maybeSetVideoSendInitialBitRate(e,t){let n=t.videoSendInitialBitrate;if(!n)return e;let i=n;const o=t.videoSendBitrate;o&&(n>o&&(trace(`Clamping initial bitrate to max bitrate of ${o} kbps.`),n=o,t.videoSendInitialBitrate=n),i=o);if(-1===findLine(e.split("\r\n"),"m=","video"))return trace("Failed to find video m-line"),e;const r=t.videoRecvCodec||"";return e=setCodecParam(e,r,"x-google-min-bitrate",t.videoSendInitialBitrate||""),e=setCodecParam(e,r,"x-google-max-bitrate",i.toString())}function removePayloadTypeFromMline(e,t){const n=e.split(" ");for(let e=0;e<
|
|
1
|
+
export function trace(e){if(e.endsWith("\n")&&(e=e.substring(0,e.length-1)),window.performance){const t=(window.performance.now()/1e3).toFixed(3);console.log(`${t}: ${e}`)}else console.log(e)}function iceCandidateType(e){return e.split(" ")[7]}export function isValidIceCandidate({candidate:e},t){return!(!e||e.includes("tcp"))&&(!t||"relay"!==t.iceTransportPolicy||"relay"===iceCandidateType(e))}function maybeSetOpusOptions(e,t){return"true"===t.opusStereo?e=setCodecParam(e,"opus/48000","stereo","1"):"false"===t.opusStereo&&(e=removeCodecParam(e,"opus/48000","stereo")),"true"===t.opusFec?e=setCodecParam(e,"opus/48000","useinbandfec","1"):"false"===t.opusFec&&(e=removeCodecParam(e,"opus/48000","useinbandfec")),"true"===t.opusDtx?e=setCodecParam(e,"opus/48000","usedtx","1"):"false"===t.opusDtx&&(e=removeCodecParam(e,"opus/48000","usedtx")),t.opusMaxPbr&&(e=setCodecParam(e,"opus/48000","maxplaybackrate",t.opusMaxPbr)),e}function maybeSetAudioSendBitRate(e,t){return t.audioSendBitrate?(trace(`Prefer audio send bitrate: ${t.audioSendBitrate}`),preferBitRate(e,t.audioSendBitrate,"audio")):e}function maybeSetAudioReceiveBitRate(e,t){return t.audioRecvBitrate?(trace(`Prefer audio receive bitrate: ${t.audioRecvBitrate}`),preferBitRate(e,t.audioRecvBitrate,"audio")):e}function maybeSetVideoSendBitRate(e,t){return t.videoSendBitrate?(trace(`Prefer video send bitrate: ${t.videoSendBitrate}`),preferBitRate(e,t.videoSendBitrate,"video")):e}function maybeSetVideoReceiveBitRate(e,t){return t.videoRecvBitrate?(trace(`Prefer video receive bitrate: ${t.videoRecvBitrate}`),preferBitRate(e,t.videoRecvBitrate,"video")):e}function preferBitRate(e,t,n){const i=e.split("\r\n"),o=findLine(i,"m=",n);if(-1===o)return trace("Failed to add bandwidth line to sdp, as no m-line found"),e;let r=findLineInRange(i,o+1,-1,"m=");-1===r&&(r=i.length);const a=findLineInRange(i,o+1,r,"c=");if(-1===a)return trace("Failed to add bandwidth line to sdp, as no c-line found"),e;const d=findLineInRange(i,a+1,r,"b=AS");d>=0&&i.splice(d,1);const c=`b=AS:${t}`;return i.splice(a+1,0,c),e=i.join("\r\n")}function maybeSetVideoSendInitialBitRate(e,t){let n=t.videoSendInitialBitrate;if(!n)return e;let i=n;const o=t.videoSendBitrate;o&&(n>o&&(trace(`Clamping initial bitrate to max bitrate of ${o} kbps.`),n=o,t.videoSendInitialBitrate=n),i=o);if(-1===findLine(e.split("\r\n"),"m=","video"))return trace("Failed to find video m-line"),e;const r=t.videoRecvCodec||"";return e=setCodecParam(e,r,"x-google-min-bitrate",t.videoSendInitialBitrate||""),e=setCodecParam(e,r,"x-google-max-bitrate",i.toString())}function removePayloadTypeFromMline(e,t){const n=e.split(" "),{length:i}=n;for(let e=0;e<i;++e)n[e]===t.toString()&&n.splice(e,1);return n.join(" ")}function removeCodecByName(e,t){const n=findLine(e,"a=rtpmap",t);if(-1===n)return e;const i=getCodecPayloadTypeFromLine(e[n]);e.splice(n,1);const o=findLine(e,"m=","video");return-1===o||(e[o]=removePayloadTypeFromMline(e[o],i)),e}function removeCodecByPayloadType(e,t){const n=findLine(e,"a=rtpmap",t.toString());if(-1===n)return e;e.splice(n,1);const i=findLine(e,"m=","video");return-1===i||(e[i]=removePayloadTypeFromMline(e[i],t)),e}function maybeRemoveVideoFec(e,t){if("false"!==t.videoFec)return e;let n=e.split("\r\n"),i=findLine(n,"a=rtpmap","red");if(-1===i)return e;const o=getCodecPayloadTypeFromLine(n[i]);if(n=removeCodecByPayloadType(n,o),n=removeCodecByName(n,"ulpfec"),i=findLine(n,"a=fmtp",o.toString()),-1===i)return e;const r=parseFmtpLine(n[i]).pt;return null==r?e:(n.splice(i,1),n=removeCodecByPayloadType(n,r),n.join("\r\n"))}function maybePreferAudioSendCodec(e,t){return maybePreferCodec(e,"audio","send",t.audioSendCodec)}function maybePreferAudioReceiveCodec(e,t){return maybePreferCodec(e,"audio","receive",t.audioRecvCodec)}function maybePreferVideoSendCodec(e,t){return maybePreferCodec(e,"video","send",t.videoSendCodec)}function maybePreferVideoReceiveCodec(e,t){return maybePreferCodec(e,"video","receive",t.videoRecvCodec)}function maybePreferCodec(e,t,n,i){if(!i)return e;const o=e.split("\r\n"),r=findLine(o,"m=",t);if(-1===r)return e;const a=getCodecPayloadType(o,i);return a&&(o[r]=setDefaultCodec(o[r],a)),e=o.join("\r\n")}function setCodecParam(e,t,n,i){const o=e.split("\r\n"),r=findFmtpLine(o,t);if(null===r){const r=findLine(o,"a=rtpmap",t);if(-1===r)return e;const a={pt:getCodecPayloadTypeFromLine(o[r]).toString(),params:{[n]:i}};o.splice(r+1,0,writeFmtpLine(a))}else{const e=parseFmtpLine(o[r]);e.params[n]=i,o[r]=writeFmtpLine(e)}return e=o.join("\r\n")}function removeCodecParam(e,t,n){const i=e.split("\r\n"),o=findFmtpLine(i,t);if(null===o)return e;const r=parseFmtpLine(i[o]);if(r){delete r.params[n];const e=writeFmtpLine(r);null===e?i.splice(o,1):i[o]=e}return e=i.join("\r\n")}function parseFmtpLine(e){const t={},n=e.indexOf(" "),i=e.substring(n+1).split("; "),o=/a=fmtp:(\d+)/.exec(e);o&&2===o.length&&(t.pt=o[1]);const r={};return i.forEach(e=>{const t=e.split("=");2===t.length&&(r[t[0]]=t[1])}),t.params=r,t}function writeFmtpLine(e){if(!e.hasOwnProperty("pt")||!e.hasOwnProperty("params"))return"";const{pt:t="",params:n={}}=e,i=Object.entries(n).map(([e,t])=>`${e}=${t}`);return 0===i.length?"":`a=fmtp:${t.toString()} ${i.join("; ")}`}function findFmtpLine(e,t){const n=getCodecPayloadType(e,t);return n?findLine(e,`a=fmtp:${n.toString()}`):null}function findLine(e,t,n){return findLineInRange(e,0,-1,t,n)}function findLineInRange(e,t,n,i,o){const r=-1!==n?n:e.length;for(let n=t;n<r;++n)if(e[n].startsWith(i)&&(!o||e[n].toLowerCase().includes(o.toLowerCase())))return n;return-1}function getCodecPayloadType(e,t){const n=findLine(e,"a=rtpmap",t);return n>=0?getCodecPayloadTypeFromLine(e[n]):null}function getCodecPayloadTypeFromLine(e){const t=/a=rtpmap:(\d+) [a-zA-Z0-9-]+\/\d+/.exec(e);return t&&2===t.length?t[1]:""}function setDefaultCodec(e,t){const n=e.split(" "),i=n.slice(0,3);i.push(t);const{length:o}=n;for(let e=3;e<o;e++)n[e]!==t&&i.push(n[e]);return i.join(" ")}export function prepareLocalDescription(e,t={}){let n=maybePreferAudioReceiveCodec(e.sdp||"",t);n=maybePreferVideoReceiveCodec(n,t),n=maybeSetAudioReceiveBitRate(n,t),n=maybeSetVideoReceiveBitRate(n,t),n=maybeRemoveVideoFec(n,t);return{sdp:n,type:e.type}}export function prepareRemoteDescription(e,t={}){let n=maybeSetOpusOptions(e.sdp||"",t);n=maybePreferAudioSendCodec(n,t),n=maybePreferVideoSendCodec(n,t),n=maybeSetAudioSendBitRate(n,t),n=maybeSetVideoSendBitRate(n,t),n=maybeSetVideoSendInitialBitRate(n,t),n=maybeRemoveVideoFec(n,t);return{sdp:n,type:e.type}}
|
package/ws/WSController.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import ReconnectingWebSocket,{}from"reconnecting-websocket";import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{delayed}from"@js-toolkit/utils/delayed";import{EventEmitterListener}from"../EventEmitterListener";function getNotConnectedError(){return new Error("The object is not connected yet.")}export class WSController extends EventEmitter{get Events(){return WSController.Events}logger;ws;listener;reconnectOnIdle;halfOpen;constructor(e,t){super();const{logger:n,protocols:s,binaryType:o,idleTimeout:r,halfOpenDetection:i,startClosed:c,...l}=t??{};this.logger=n??console,this.ws=new ReconnectingWebSocket(e,s,{...l,startClosed:!0}),null!=o&&(this.ws.binaryType=o),this.listener=new EventEmitterListener(this.ws),r&&r>0&&(this.reconnectOnIdle=delayed((
|
|
1
|
+
import ReconnectingWebSocket,{}from"reconnecting-websocket";import{EventEmitter}from"@js-toolkit/utils/EventEmitter";import{delayed}from"@js-toolkit/utils/delayed";import{EventEmitterListener}from"../EventEmitterListener";function getNotConnectedError(){return new Error("The object is not connected yet.")}export class WSController extends EventEmitter{get Events(){return WSController.Events}logger;ws;listener;reconnectOnIdle;halfOpen;constructor(e,t){super();const{logger:n,protocols:s,binaryType:o,idleTimeout:r,halfOpenDetection:i,startClosed:c,...l}=t??{};this.logger=n??console,this.ws=new ReconnectingWebSocket(e,s,{...l,startClosed:!0}),null!=o&&(this.ws.binaryType=o),this.listener=new EventEmitterListener(this.ws),r&&r>0&&(this.reconnectOnIdle=delayed(()=>{this.logger.info(`WS connection reconnecting after ${r}ms due to inactivity.`),this.ws.reconnect()},r)),this.halfOpen=(()=>{if(!i)return;const{pingTimeout:e=12e3,outMessage:t=()=>JSON.stringify({type:"pong"}),inMessageFilter:n=e=>e&&"object"==typeof e&&"ping"===e.type}=i,s=delayed(()=>{this.logger.info(`WS connection reconnecting after ${e}ms due to the probability of a half-open connection.`),this.ws.reconnect()},e),o=()=>{s(),this.ws.send("function"!=typeof t||t instanceof Blob?t:t())};return{heartbeat:o,cancel:()=>s.cancel(),onMessage:({data:e})=>{n(e)?o():s()}}})(),this.listener.on("open",()=>{this.reconnectOnIdle&&this.reconnectOnIdle(),this.halfOpen?.heartbeat(),this.emit(this.Events.Connected)}).on("close",({code:e})=>{this.reconnectOnIdle?.cancel(),this.halfOpen?.cancel(),null!=t?.maxRetries&&this.ws.readyState===this.ws.CLOSED&&this.ws.retryCount===t.maxRetries&&this.close(e,`Failed to connect after ${t.maxRetries} attempts.`)}).on("message",e=>{this.reconnectOnIdle&&this.reconnectOnIdle(),this.halfOpen?.onMessage(e),this.emit(this.Events.Message,e)}).on("error",({error:e,message:t})=>{this.emit(this.Events.Error,{error:e,message:t})}),this.halfOpen&&(this.isConnected()||this.ws.readyState===this.ws.CONNECTING)&&this.halfOpen.heartbeat(),c||this.connect()}isConnected(){return this.ws.readyState===this.ws.OPEN}getUrl(){return this.ws.url}connect(){this.ws.reconnect()}send(e){if(!this.ws)throw getNotConnectedError();this.ws.send(e)}close(e,t){const n=!!this.ws;try{this.reconnectOnIdle&&this.reconnectOnIdle.cancel(),this.halfOpen&&this.halfOpen.cancel(),this.ws.close(e,t)}catch(e){this.logger.warn(e)}n&&this.emit(this.Events.Closed,t?{reason:t}:void 0)}destroy(){this.close(),this.listener.removeAllListeners(),this.removeAllListeners()}[Symbol.dispose](){this.destroy()}}!function(e){let t;!function(e){e.Connected="Connected",e.Message="Message",e.Error="Error",e.Closed="Closed"}(t=e.Events||(e.Events={}))}(WSController||(WSController={}));
|
package/takeSnapshot.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export declare function get2dContextError(): Error;
|
|
2
|
-
export interface TakeSnapshotOptions {
|
|
3
|
-
width?: number | undefined;
|
|
4
|
-
height?: number | undefined;
|
|
5
|
-
type?: string | undefined;
|
|
6
|
-
quality?: number | undefined;
|
|
7
|
-
}
|
|
8
|
-
export declare function takeSnapshot(element: CanvasImageSource, { width, height, type, quality, }?: TakeSnapshotOptions): string;
|
|
9
|
-
export declare function takeSnapshotAsync(element: CanvasImageSource, { width, height, type, quality, }?: TakeSnapshotOptions): Promise<Blob>;
|
package/takeSnapshot.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{hasIn}from"@js-toolkit/utils/hasIn";export function get2dContextError(){return new Error("Failed to get canvas 2d context.")}const getDefaultWidth=t=>t instanceof HTMLVideoElement?t.videoWidth:hasIn(t,"displayWidth")?t.displayWidth:t.width instanceof SVGAnimatedLength?t.width.animVal.value:t.width,getDefaultHeight=t=>t instanceof HTMLVideoElement?t.videoHeight:hasIn(t,"displayHeight")?t.displayHeight:t.height instanceof SVGAnimatedLength?t.height.animVal.value:t.height;export function takeSnapshot(t,{width:e=getDefaultWidth(t),height:i=getDefaultHeight(t),type:n="image/jpeg",quality:a=1}={}){const o=document.createElement("canvas");o.width=e,o.height=i;const h=o.getContext("2d");if(!h)throw get2dContextError();return h.drawImage(t,0,0),o.toDataURL(n,a)}export function takeSnapshotAsync(t,{width:e=getDefaultWidth(t),height:i=getDefaultHeight(t),type:n="image/jpeg",quality:a=1}={}){return new Promise(((o,h)=>{const d=document.createElement("canvas");d.width=e,d.height=i;const g=d.getContext("2d");if(!g)throw get2dContextError();g.drawImage(t,0,0),d.toBlob((t=>{null==t?h(new Error("Unable get blob")):o(t)}),n,a)}))}
|