@readium/navigator 2.11.1 → 2.12.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/dist/divina/DivinaNavigator.js +1 -1
- package/dist/epub/EpubNavigator.js +1 -1
- package/dist/epub/frame/FramePoolManager.js +1 -1
- package/dist/index.js +1 -1
- package/dist/preferences/guards.js +1 -1
- package/dist/readaloud/GuidedNavigationProvider.js +1 -0
- package/dist/readaloud/ReadAloudNavigator.js +1 -0
- package/dist/readaloud/ReadingUnit.js +1 -0
- package/dist/readaloud/SpeechProgress.js +1 -0
- package/dist/readaloud/preferences/ReadAloudDefaults.js +1 -0
- package/dist/readaloud/preferences/ReadAloudPreferences.js +1 -0
- package/dist/readaloud/preferences/ReadAloudPreferencesEditor.js +1 -0
- package/dist/readaloud/preferences/ReadAloudSettings.js +1 -0
- package/dist/webpub/WebPubFrameManager.js +1 -1
- package/dist/webpub/WebPubFramePoolManager.js +1 -1
- package/dist/webpub/WebPubNavigator.js +1 -1
- package/package.json +8 -6
- package/src/divina/DivinaNavigator.ts +1 -0
- package/src/epub/EpubNavigator.ts +127 -21
- package/src/epub/frame/FramePoolManager.ts +5 -0
- package/src/index.ts +1 -0
- package/src/preferences/guards.ts +11 -0
- package/src/readaloud/GuidedNavigationProvider.ts +87 -0
- package/src/readaloud/ReadAloudNavigator.ts +949 -0
- package/src/readaloud/ReadingUnit.ts +154 -0
- package/src/readaloud/SpeechProgress.ts +60 -0
- package/src/readaloud/index.ts +17 -0
- package/src/readaloud/preferences/ReadAloudDefaults.ts +24 -0
- package/src/readaloud/preferences/ReadAloudPreferences.ts +104 -0
- package/src/readaloud/preferences/ReadAloudPreferencesEditor.ts +115 -0
- package/src/readaloud/preferences/ReadAloudSettings.ts +44 -0
- package/src/readaloud/preferences/index.ts +4 -0
- package/src/webpub/WebPubFrameManager.ts +4 -0
- package/src/webpub/WebPubFramePoolManager.ts +5 -0
- package/src/webpub/WebPubNavigator.ts +114 -10
- package/types/src/epub/EpubNavigator.d.ts +26 -1
- package/types/src/epub/frame/FramePoolManager.d.ts +2 -0
- package/types/src/index.d.ts +1 -0
- package/types/src/preferences/guards.d.ts +1 -0
- package/types/src/readaloud/GuidedNavigationProvider.d.ts +28 -0
- package/types/src/readaloud/ReadAloudNavigator.d.ts +158 -0
- package/types/src/readaloud/ReadingUnit.d.ts +58 -0
- package/types/src/readaloud/SpeechProgress.d.ts +19 -0
- package/types/src/readaloud/index.d.ts +6 -0
- package/types/src/readaloud/preferences/ReadAloudDefaults.d.ts +11 -0
- package/types/src/readaloud/preferences/ReadAloudPreferences.d.ts +58 -0
- package/types/src/readaloud/preferences/ReadAloudPreferencesEditor.d.ts +37 -0
- package/types/src/readaloud/preferences/ReadAloudSettings.d.ts +26 -0
- package/types/src/readaloud/preferences/index.d.ts +4 -0
- package/types/src/webpub/WebPubFrameManager.d.ts +1 -0
- package/types/src/webpub/WebPubFramePoolManager.d.ts +2 -0
- package/types/src/webpub/WebPubNavigator.d.ts +25 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Layout as l,Link as f}from"@readium/shared";import{VisualNavigator as m}from"../Navigator.js";import{getContentWidth as P}from"../helpers/dimensions.js";import{NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as d}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as y,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as p}from"../peripherals/KeyboardPeripherals.js";import{KeyboardConditionBridge as _}from"../peripherals/KeyboardConditionBridge.js";import{DivinaSpreader as b}from"./DivinaSpreader.js";import{DivinaPageManager as v}from"./DivinaPageManager.js";import{DivinaPagedPresenter as w}from"./DivinaPagedPresenter.js";import{DivinaScrolledPresenter as L}from"./DivinaScrolledPresenter.js";import{isTypedOMSupported as k}from"../epub/fxl/FXLPeripherals.js";import{DivinaNavigatorProtector as E}from"./protection/DivinaNavigatorProtector.js";import{DivinaDefaults as S}from"./preferences/DivinaDefaults.js";import{DivinaPreferences as C}from"./preferences/DivinaPreferences.js";import{DivinaSettings as g}from"./preferences/DivinaSettings.js";import{DivinaPreferencesEditor as u}from"./preferences/DivinaPreferencesEditor.js";const T=o=>({positionChanged:o.positionChanged||(()=>{}),timelineItemChanged:o.timelineItemChanged||(()=>{}),tap:o.tap||(()=>!1),click:o.click||(()=>!1),zoom:o.zoom||(()=>{}),miscPointer:o.miscPointer||(()=>{}),scroll:o.scroll||(()=>{}),customEvent:o.customEvent||(()=>{}),handleLocator:o.handleLocator||(()=>!1),contentProtection:o.contentProtection||(()=>{}),contextMenu:o.contextMenu||(()=>{}),peripheral:o.peripheral||(()=>{})});class G extends m{constructor(e,t,i,n=[],r=void 0,s={preferences:{},defaults:{}}){super(),this._destroyed=!1,this._isNavigating=!1,this._timelineAugmented=!1,this._preferencesEditor=null,this.pool=new Map,this.pagedPresenter=null,this.scrolledPresenter=null,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._keyboardConditionBridge=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._applying=Promise.resolve(),this.pub=t,this.container=e,this.listeners=T(i),this.currentLocation=r,n.length&&(this.positions=n),this._preferences=new C(s.preferences),this._defaults=new S(s.defaults),this._settings=new g(this._preferences,this._defaults,this.manifestScrolled),this.spreader=new b(t),this._contentProtection=s.contentProtection||{},this._keyboardPeripherals=this.mergeKeyboardPeripherals(this._contentProtection,s.keyboardPeripherals||[]),(this._contentProtection.disableContextMenu||this._contentProtection.checkAutomation||this._contentProtection.checkIFrameEmbedding||this._contentProtection.monitorDevTools||this._contentProtection.protectPrinting?.disable||this._contentProtection.disableDragAndDrop||this._contentProtection.protectCopy)&&(this._navigatorProtector=new E(this._contentProtection),this._suspiciousActivityListener=a=>{const{type:h,...c}=a.detail;h==="context_menu"?this.listeners.contextMenu(c):this.listeners.contentProtection(h,c)},window.addEventListener(d,this._suspiciousActivityListener)),this._keyboardPeripherals.length>0&&(this._keyboardConditionBridge=new _(this._keyboardPeripherals,a=>{this._keyboardPeripheralsManager?.destroy(),this._keyboardPeripheralsManager=a.length>0?new y({keyboardPeripherals:a}):null}),this._keyboardConditionBridge.setup(),this._keyboardPeripheralListener=a=>{const h=a.detail;this.listeners.peripheral(h)},window.addEventListener(p,this._keyboardPeripheralListener)),this.resizeObserver=new ResizeObserver(()=>this.ownerWindow.requestAnimationFrame(()=>this.resizeHandler())),this.resizeObserver.observe(this.container.parentElement||document.documentElement)}get manifestScrolled(){return this.pub.metadata.effectiveLayout===l.scrolled}get ownerWindow(){return this.container.ownerDocument.defaultView||window}get publication(){return this.pub}get timeline(){const e=this.pub.timeline;if(!this._timelineAugmented&&this.positions?.length){const t=this.positions,i=new Set;e.augment((n,r)=>{if(n.children?.length)return{};if(i.has(r.href))return{};const s=t.find(a=>a.href===r.href);return s?(i.add(r.href),{position:s.locations.position}):{}}),this._timelineAugmented=!0}return this._wrappedTimeline||(this._wrappedTimeline=e),this._wrappedTimeline}_notifyTimelineChange(e){const t=this.timeline.locate(e);t!==this._currentTimelineItem&&(this._currentTimelineItem=t,this.listeners.timelineItemChanged(t))}get layout(){return this._settings.scrolled?l.scrolled:l.fixed}get readingProgression(){return this.pub.metadata.effectiveReadingProgression}get presenter(){return this.pagedPresenter??this.scrolledPresenter}async load(){if(this.positions?.length||(this.positions=await this.pub.positionsFromManifest()),this._destroyed)return;this.positions?.length||(this.positions=this.synthesizePositions());const e=async(i,n)=>{const r=this.pub.get(i),s=await r.read(void 0,{signal:n});if(!s)throw new Error(`Empty resource: ${i.href}`);const a=await r.link(),h=a.type!==void 0?a.mediaType:i.mediaType;return new Blob([s],{type:h.string})},t=()=>this._settings.quality;if(this.spreader.pages.forEach(i=>{this.pool.set(i.index,new v(i,e,t))}),this.applyBackground(),this.createPresenter(),!this._destroyed)return this.resizeHandler(),this.currentLocation===void 0?this.currentLocation=this.positions[0]:this.currentLocation=this.completeLocator(this.currentLocation),new Promise(i=>{if(this._destroyed)return i(!1);this.go(this.currentLocation,!1,n=>i(n))})}synthesizePositions(){const e=this.pub.readingOrder.items.length;return this.pub.readingOrder.items.map((t,i)=>t.locator.copyWithLocations({progression:0,position:i+1,totalProgression:e>0?i/e:0}))}createPresenter(){this._settings.scrolled?(this.scrolledPresenter=new L(this.container,this.spreader,this.pool,this._settings.stripWidth),this.scrolledPresenter.listener=(e,t)=>{switch(e){case"scroll":this.listeners.scroll(t);break;case"position":this.updateLocationFromScroll(t);break;case"tap":case"click":this.handlePointer(e,t);break}}):(this.pagedPresenter=new w(this.container,this.pub,this.spreader,this.pool,this._settings.spreads),this.pagedPresenter.listener=(e,t)=>{switch(e){case"no_more":this.changeSpread(1);break;case"no_less":this.changeSpread(-1);break;case"zoom":this.listeners.zoom(t);break;case"tap":case"click":this.handlePointer(e,t);break}})}async destroyPresenter(){this.pagedPresenter&&(await this.pagedPresenter.destroy(),this.pagedPresenter=null),this.scrolledPresenter&&(await this.scrolledPresenter.destroy(),this.scrolledPresenter=null)}handlePointer(e,t){const i={defaultPrevented:!1,doNotDisturb:t.doNotDisturb,interactiveElement:void 0,cssSelector:void 0,targetElement:"",targetFrameSrc:"",x:t.x,y:t.y};if((e==="click"?this.listeners.click(i):this.listeners.tap(i))||t.doNotDisturb)return;const r=window.devicePixelRatio||1;if(this._settings.scrolled){const s=this.container.clientHeight*r/4;t.y>=s&&t.y<=s*3?this.listeners.miscPointer(1):t.y<s?this.goBackward(!0,()=>{}):this.goForward(!0,()=>{})}else{const s=this.container.clientWidth*r/4;t.x>=s&&t.x<=s*3?this.listeners.miscPointer(1):t.x<s?this.goLeft(!1,()=>{}):this.goRight(!1,()=>{})}}changeSpread(e){const t=this.pagedPresenter;return!t||!(e>0?t.next():t.prev())?!1:(this.setLocationToIndex(t.currentIndex),t.update(),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),!0)}setLocationToIndex(e){const t=this.pub.readingOrder.items[e];if(!t)return;const i=this.positions.find(n=>n.href===t.href);this.currentLocation=i??this.synthesizePositions()[e]}updateLocationFromScroll(e){const t=this.scrolledPresenter;if(!t)return;this.setLocationToIndex(e);const i=this.pub.readingOrder.items.length,n=t.currentPageProgression;this.currentLocation=this.currentLocation.copyWithLocations({progression:n,totalProgression:i>0?Math.min((e+n)/i,1):0}),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation)}applyBackground(){const e=this._settings.backgroundColor;if(e){this.container.style.background=e;const t=this.isDarkColor(e);t===null?(this.container.style.removeProperty("color-scheme"),this.container.style.removeProperty("scrollbar-color")):(this.container.style.colorScheme=t?"dark":"light",this.container.style.scrollbarColor=`${t?"rgba(255, 255, 255, 0.3)":"rgba(0, 0, 0, 0.3)"} ${e}`)}else this.container.style.removeProperty("background"),this.container.style.removeProperty("color-scheme"),this.container.style.removeProperty("scrollbar-color")}isDarkColor(e){const t=this.container.ownerDocument,i=t.createElement("div");i.style.display="none",i.style.color=e,t.body.appendChild(i);const n=(t.defaultView||window).getComputedStyle(i).color;i.remove();const r=n.match(/rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/);return r?(.2126*+r[1]+.7152*+r[2]+.0722*+r[3])/255<.45:null}resizeHandler(){const e=this.container.parentElement||document.documentElement,t=window.devicePixelRatio||1,i=Math.floor((P(e)-this._settings.constraint)*t)/t;k()?this.container.attributeStyleMap.set("width",CSS.px(i)):this.container.style.width=`${i}px`,this.pagedPresenter?.resizeHandler(),this.scrolledPresenter?.resizeHandler()}completeLocator(e){if(!e.href){let t=!1;if(typeof e.locations.position=="number"){const i=this.positions.find(n=>n.locations.position===e.locations.position);i&&(e=i.copyWithLocations(e.locations),t=!0)}if(!t&&typeof e.locations?.totalProgression=="number"){const i=e.locations.totalProgression;let n=0,r=1/0;for(let s=0;s<this.positions.length;s++){const h=this.positions[s].locations.totalProgression??s/this.positions.length,c=Math.abs(h-i);c<r&&(r=c,n=s)}e=this.positions[n].copyWithLocations(e.locations)}}return e}findReadingOrderIndex(e){const t=this.pub.readingOrder.findIndexWithHref(e);if(t>=0)return t;const i=this.pub.baseURL,n=new f({href:e}).toURL(i)??e,r=s=>(s.toURL(i)??s.href)===n;return this.pub.readingOrder.items.findIndex(s=>r(s)||!!s.alternates?.items.some(r))}go(e,t,i){e=this.completeLocator(e);const n=e.href?.split("#")[0],r=n?this.findReadingOrderIndex(n):-1;if(r<0)return i(this.listeners.handleLocator(e));if(this._isNavigating){i(!1);return}this._isNavigating=!0;try{if(this.scrolledPresenter){const s=e.locations?.progression||0;this.scrolledPresenter.goToItem(r,t,s),this.scrolledPresenter.update()}else this.pagedPresenter&&(this.pagedPresenter.goToItem(r,t),this.pagedPresenter.update());this.setLocationToIndex(this.pagedPresenter?this.pagedPresenter.currentIndex:r),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),i(!0)}finally{this._isNavigating=!1}}goLink(e,t,i){return this.go(e.locator,t,i)}goForward(e,t){if(this.scrolledPresenter){t(this.scrolledPresenter.next(e));return}t(this.changeSpread(1))}goBackward(e,t){if(this.scrolledPresenter){t(this.scrolledPresenter.prev(e));return}t(this.changeSpread(-1))}scrollBy(e,t,i){if(this.scrolledPresenter){i(e>=0?this.scrolledPresenter.next(t,e):this.scrolledPresenter.prev(t,-e));return}i(this.changeSpread(e>=0?1:-1))}zoomIn(){this.pagedPresenter?.peripherals.zoomIn()}zoomOut(){this.pagedPresenter?.peripherals.zoomOut()}zoomReset(){this.pagedPresenter?.peripherals.resetZoom()}get currentLocator(){return this.currentLocation}get viewport(){return this.presenter?.viewport??{readingOrder:[],progressions:new Map,positions:null}}get isScrollStart(){const e=this.viewport.readingOrder[0];return(e?this.viewport.progressions.get(e):void 0)?.start===0}get isScrollEnd(){const e=this.viewport.readingOrder[this.viewport.readingOrder.length-1];return(e?this.viewport.progressions.get(e):void 0)?.end===1}get canGoBackward(){const e=this.pub.readingOrder.items[0]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.start===0)}get canGoForward(){const e=this.pub.readingOrder.items[this.pub.readingOrder.items.length-1]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.end===1)}get settings(){return Object.freeze({...this._settings})}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new u(this._preferences,this.settings,this.pub.metadata)),this._preferencesEditor}async submitPreferences(e){this._preferences=this._preferences.merging(e),this._applying=this._applying.then(()=>this.applyPreferences()),await this._applying}async applyPreferences(){const e=this._settings;if(this._settings=new g(this._preferences,this._defaults,this.manifestScrolled),this._preferencesEditor!==null&&(this._preferencesEditor=new u(this._preferences,this.settings,this.pub.metadata)),e.backgroundColor!==this._settings.backgroundColor&&this.applyBackground(),e.constraint!==this._settings.constraint&&this.resizeHandler(),e.scrolled!==this._settings.scrolled){if(!this.presenter)return;const t=this.currentLocation;if(await this.destroyPresenter(),this._destroyed)return;this.createPresenter(),this.resizeHandler(),this.go(t,!1,()=>{});return}e.spreads!==this._settings.spreads&&this.pagedPresenter?.setSpreads(this._settings.spreads),e.stripWidth!==this._settings.stripWidth&&this.scrolledPresenter?.applyStripWidth(this._settings.stripWidth),e.quality!==this._settings.quality&&(this.pool.forEach(t=>t.unload()),this.pagedPresenter?.update(),this.scrolledPresenter?.update())}async destroy(){this._destroyed=!0,this._suspiciousActivityListener&&window.removeEventListener(d,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(p,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardConditionBridge?.destroy(),this._keyboardPeripheralsManager?.destroy(),this.resizeObserver.disconnect(),await this.destroyPresenter(),this.pool.forEach(e=>e.destroy()),this.pool.clear(),Array.from(this.container.childNodes).forEach(e=>{(e.nodeType===Node.ELEMENT_NODE||e.nodeType===Node.TEXT_NODE)&&e.remove()})}}export{G as DivinaNavigator};
|
|
1
|
+
import{Layout as l,Link as f}from"@readium/shared";import{VisualNavigator as m}from"../Navigator.js";import{getContentWidth as P}from"../helpers/dimensions.js";import{NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as d}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as y,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as p}from"../peripherals/KeyboardPeripherals.js";import{KeyboardConditionBridge as _}from"../peripherals/KeyboardConditionBridge.js";import{DivinaSpreader as b}from"./DivinaSpreader.js";import{DivinaPageManager as v}from"./DivinaPageManager.js";import{DivinaPagedPresenter as w}from"./DivinaPagedPresenter.js";import{DivinaScrolledPresenter as L}from"./DivinaScrolledPresenter.js";import{isTypedOMSupported as k}from"../epub/fxl/FXLPeripherals.js";import{DivinaNavigatorProtector as E}from"./protection/DivinaNavigatorProtector.js";import{DivinaDefaults as C}from"./preferences/DivinaDefaults.js";import{DivinaPreferences as S}from"./preferences/DivinaPreferences.js";import{DivinaSettings as g}from"./preferences/DivinaSettings.js";import{DivinaPreferencesEditor as u}from"./preferences/DivinaPreferencesEditor.js";const T=o=>({positionChanged:o.positionChanged||(()=>{}),timelineItemChanged:o.timelineItemChanged||(()=>{}),tap:o.tap||(()=>!1),click:o.click||(()=>!1),zoom:o.zoom||(()=>{}),miscPointer:o.miscPointer||(()=>{}),scroll:o.scroll||(()=>{}),customEvent:o.customEvent||(()=>{}),handleLocator:o.handleLocator||(()=>!1),contentProtection:o.contentProtection||(()=>{}),contextMenu:o.contextMenu||(()=>{}),peripheral:o.peripheral||(()=>{})});class G extends m{constructor(e,t,i,n=[],r=void 0,s={preferences:{},defaults:{}}){super(),this._destroyed=!1,this._isNavigating=!1,this._timelineAugmented=!1,this._preferencesEditor=null,this.pool=new Map,this.pagedPresenter=null,this.scrolledPresenter=null,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._keyboardConditionBridge=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._applying=Promise.resolve(),this.pub=t,this.container=e,this.listeners=T(i),this.currentLocation=r,n.length&&(this.positions=n),this._preferences=new S(s.preferences),this._defaults=new C(s.defaults),this._settings=new g(this._preferences,this._defaults,this.manifestScrolled),this.spreader=new b(t),this._contentProtection=s.contentProtection||{},this._keyboardPeripherals=this.mergeKeyboardPeripherals(this._contentProtection,s.keyboardPeripherals||[]),(this._contentProtection.disableContextMenu||this._contentProtection.checkAutomation||this._contentProtection.checkIFrameEmbedding||this._contentProtection.monitorDevTools||this._contentProtection.protectPrinting?.disable||this._contentProtection.disableDragAndDrop||this._contentProtection.protectCopy)&&(this._navigatorProtector=new E(this._contentProtection),this._suspiciousActivityListener=a=>{const{type:h,...c}=a.detail;h==="context_menu"?this.listeners.contextMenu(c):this.listeners.contentProtection(h,c)},window.addEventListener(d,this._suspiciousActivityListener)),this._keyboardPeripherals.length>0&&(this._keyboardConditionBridge=new _(this._keyboardPeripherals,a=>{this._keyboardPeripheralsManager?.destroy(),this._keyboardPeripheralsManager=a.length>0?new y({keyboardPeripherals:a}):null}),this._keyboardConditionBridge.setup(),this._keyboardPeripheralListener=a=>{const h=a.detail;this.listeners.peripheral(h)},window.addEventListener(p,this._keyboardPeripheralListener)),this.resizeObserver=new ResizeObserver(()=>this.ownerWindow.requestAnimationFrame(()=>this.resizeHandler())),this.resizeObserver.observe(this.container.parentElement||document.documentElement)}get manifestScrolled(){return this.pub.metadata.effectiveLayout===l.scrolled}get ownerWindow(){return this.container.ownerDocument.defaultView||window}get publication(){return this.pub}get timeline(){const e=this.pub.timeline;if(!this._timelineAugmented&&this.positions?.length){const t=this.positions,i=new Set;e.augment((n,r)=>{if(n.children?.length)return{};if(i.has(r.href))return{};const s=t.find(a=>a.href===r.href);return s?(i.add(r.href),{position:s.locations.position}):{}}),this._timelineAugmented=!0}return this._wrappedTimeline||(this._wrappedTimeline=e),this._wrappedTimeline}_notifyTimelineChange(e){const t=this.timeline.locate(e);t!==this._currentTimelineItem&&(this._currentTimelineItem=t,this.listeners.timelineItemChanged(t))}get layout(){return this._settings.scrolled?l.scrolled:l.fixed}get readingProgression(){return this.pub.metadata.effectiveReadingProgression}get presenter(){return this.pagedPresenter??this.scrolledPresenter}async load(){if(this.positions?.length||(this.positions=await this.pub.positionsFromManifest()),this._destroyed)return;this.positions?.length||(this.positions=this.synthesizePositions());const e=async(i,n)=>{const r=this.pub.get(i),s=await r.read(void 0,{signal:n});if(!s)throw new Error(`Empty resource: ${i.href}`);const a=await r.link(),h=a.type!==void 0?a.mediaType:i.mediaType;return new Blob([s],{type:h.string})},t=()=>this._settings.quality;if(this.spreader.pages.forEach(i=>{this.pool.set(i.index,new v(i,e,t))}),this.applyBackground(),this.createPresenter(),!this._destroyed)return this.resizeHandler(),this.currentLocation===void 0?this.currentLocation=this.positions[0]:this.currentLocation=this.completeLocator(this.currentLocation),new Promise(i=>{if(this._destroyed)return i(!1);this.go(this.currentLocation,!1,n=>i(n))})}synthesizePositions(){const e=this.pub.readingOrder.items.length;return this.pub.readingOrder.items.map((t,i)=>t.locator.copyWithLocations({progression:0,position:i+1,totalProgression:e>0?i/e:0}))}createPresenter(){this._settings.scrolled?(this.scrolledPresenter=new L(this.container,this.spreader,this.pool,this._settings.stripWidth),this.scrolledPresenter.listener=(e,t)=>{switch(e){case"scroll":this.listeners.scroll(t);break;case"position":this.updateLocationFromScroll(t);break;case"tap":case"click":this.handlePointer(e,t);break}}):(this.pagedPresenter=new w(this.container,this.pub,this.spreader,this.pool,this._settings.spreads),this.pagedPresenter.listener=(e,t)=>{switch(e){case"no_more":this.changeSpread(1);break;case"no_less":this.changeSpread(-1);break;case"zoom":this.listeners.zoom(t);break;case"tap":case"click":this.handlePointer(e,t);break}})}async destroyPresenter(){this.pagedPresenter&&(await this.pagedPresenter.destroy(),this.pagedPresenter=null),this.scrolledPresenter&&(await this.scrolledPresenter.destroy(),this.scrolledPresenter=null)}handlePointer(e,t){const i={defaultPrevented:!1,doNotDisturb:t.doNotDisturb,interactiveElement:void 0,cssSelector:void 0,targetElement:"",targetFrameSrc:"",onContent:!1,x:t.x,y:t.y};if((e==="click"?this.listeners.click(i):this.listeners.tap(i))||t.doNotDisturb)return;const r=window.devicePixelRatio||1;if(this._settings.scrolled){const s=this.container.clientHeight*r/4;t.y>=s&&t.y<=s*3?this.listeners.miscPointer(1):t.y<s?this.goBackward(!0,()=>{}):this.goForward(!0,()=>{})}else{const s=this.container.clientWidth*r/4;t.x>=s&&t.x<=s*3?this.listeners.miscPointer(1):t.x<s?this.goLeft(!1,()=>{}):this.goRight(!1,()=>{})}}changeSpread(e){const t=this.pagedPresenter;return!t||!(e>0?t.next():t.prev())?!1:(this.setLocationToIndex(t.currentIndex),t.update(),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),!0)}setLocationToIndex(e){const t=this.pub.readingOrder.items[e];if(!t)return;const i=this.positions.find(n=>n.href===t.href);this.currentLocation=i??this.synthesizePositions()[e]}updateLocationFromScroll(e){const t=this.scrolledPresenter;if(!t)return;this.setLocationToIndex(e);const i=this.pub.readingOrder.items.length,n=t.currentPageProgression;this.currentLocation=this.currentLocation.copyWithLocations({progression:n,totalProgression:i>0?Math.min((e+n)/i,1):0}),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation)}applyBackground(){const e=this._settings.backgroundColor;if(e){this.container.style.background=e;const t=this.isDarkColor(e);t===null?(this.container.style.removeProperty("color-scheme"),this.container.style.removeProperty("scrollbar-color")):(this.container.style.colorScheme=t?"dark":"light",this.container.style.scrollbarColor=`${t?"rgba(255, 255, 255, 0.3)":"rgba(0, 0, 0, 0.3)"} ${e}`)}else this.container.style.removeProperty("background"),this.container.style.removeProperty("color-scheme"),this.container.style.removeProperty("scrollbar-color")}isDarkColor(e){const t=this.container.ownerDocument,i=t.createElement("div");i.style.display="none",i.style.color=e,t.body.appendChild(i);const n=(t.defaultView||window).getComputedStyle(i).color;i.remove();const r=n.match(/rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)/);return r?(.2126*+r[1]+.7152*+r[2]+.0722*+r[3])/255<.45:null}resizeHandler(){const e=this.container.parentElement||document.documentElement,t=window.devicePixelRatio||1,i=Math.floor((P(e)-this._settings.constraint)*t)/t;k()?this.container.attributeStyleMap.set("width",CSS.px(i)):this.container.style.width=`${i}px`,this.pagedPresenter?.resizeHandler(),this.scrolledPresenter?.resizeHandler()}completeLocator(e){if(!e.href){let t=!1;if(typeof e.locations.position=="number"){const i=this.positions.find(n=>n.locations.position===e.locations.position);i&&(e=i.copyWithLocations(e.locations),t=!0)}if(!t&&typeof e.locations?.totalProgression=="number"){const i=e.locations.totalProgression;let n=0,r=1/0;for(let s=0;s<this.positions.length;s++){const h=this.positions[s].locations.totalProgression??s/this.positions.length,c=Math.abs(h-i);c<r&&(r=c,n=s)}e=this.positions[n].copyWithLocations(e.locations)}}return e}findReadingOrderIndex(e){const t=this.pub.readingOrder.findIndexWithHref(e);if(t>=0)return t;const i=this.pub.baseURL,n=new f({href:e}).toURL(i)??e,r=s=>(s.toURL(i)??s.href)===n;return this.pub.readingOrder.items.findIndex(s=>r(s)||!!s.alternates?.items.some(r))}go(e,t,i){e=this.completeLocator(e);const n=e.href?.split("#")[0],r=n?this.findReadingOrderIndex(n):-1;if(r<0)return i(this.listeners.handleLocator(e));if(this._isNavigating){i(!1);return}this._isNavigating=!0;try{if(this.scrolledPresenter){const s=e.locations?.progression||0;this.scrolledPresenter.goToItem(r,t,s),this.scrolledPresenter.update()}else this.pagedPresenter&&(this.pagedPresenter.goToItem(r,t),this.pagedPresenter.update());this.setLocationToIndex(this.pagedPresenter?this.pagedPresenter.currentIndex:r),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),i(!0)}finally{this._isNavigating=!1}}goLink(e,t,i){return this.go(e.locator,t,i)}goForward(e,t){if(this.scrolledPresenter){t(this.scrolledPresenter.next(e));return}t(this.changeSpread(1))}goBackward(e,t){if(this.scrolledPresenter){t(this.scrolledPresenter.prev(e));return}t(this.changeSpread(-1))}scrollBy(e,t,i){if(this.scrolledPresenter){i(e>=0?this.scrolledPresenter.next(t,e):this.scrolledPresenter.prev(t,-e));return}i(this.changeSpread(e>=0?1:-1))}zoomIn(){this.pagedPresenter?.peripherals.zoomIn()}zoomOut(){this.pagedPresenter?.peripherals.zoomOut()}zoomReset(){this.pagedPresenter?.peripherals.resetZoom()}get currentLocator(){return this.currentLocation}get viewport(){return this.presenter?.viewport??{readingOrder:[],progressions:new Map,positions:null}}get isScrollStart(){const e=this.viewport.readingOrder[0];return(e?this.viewport.progressions.get(e):void 0)?.start===0}get isScrollEnd(){const e=this.viewport.readingOrder[this.viewport.readingOrder.length-1];return(e?this.viewport.progressions.get(e):void 0)?.end===1}get canGoBackward(){const e=this.pub.readingOrder.items[0]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.start===0)}get canGoForward(){const e=this.pub.readingOrder.items[this.pub.readingOrder.items.length-1]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.end===1)}get settings(){return Object.freeze({...this._settings})}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new u(this._preferences,this.settings,this.pub.metadata)),this._preferencesEditor}async submitPreferences(e){this._preferences=this._preferences.merging(e),this._applying=this._applying.then(()=>this.applyPreferences()),await this._applying}async applyPreferences(){const e=this._settings;if(this._settings=new g(this._preferences,this._defaults,this.manifestScrolled),this._preferencesEditor!==null&&(this._preferencesEditor=new u(this._preferences,this.settings,this.pub.metadata)),e.backgroundColor!==this._settings.backgroundColor&&this.applyBackground(),e.constraint!==this._settings.constraint&&this.resizeHandler(),e.scrolled!==this._settings.scrolled){if(!this.presenter)return;const t=this.currentLocation;if(await this.destroyPresenter(),this._destroyed)return;this.createPresenter(),this.resizeHandler(),this.go(t,!1,()=>{});return}e.spreads!==this._settings.spreads&&this.pagedPresenter?.setSpreads(this._settings.spreads),e.stripWidth!==this._settings.stripWidth&&this.scrolledPresenter?.applyStripWidth(this._settings.stripWidth),e.quality!==this._settings.quality&&(this.pool.forEach(t=>t.unload()),this.pagedPresenter?.update(),this.scrolledPresenter?.update())}async destroy(){this._destroyed=!0,this._suspiciousActivityListener&&window.removeEventListener(d,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(p,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardConditionBridge?.destroy(),this._keyboardPeripheralsManager?.destroy(),this.resizeObserver.disconnect(),await this.destroyPresenter(),this.pool.forEach(e=>e.destroy()),this.pool.clear(),Array.from(this.container.childNodes).forEach(e=>{(e.nodeType===Node.ELEMENT_NODE||e.nodeType===Node.TEXT_NODE)&&e.remove()})}}export{G as DivinaNavigator};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Layout as d,Profile as E,Link as _,ReadingProgression as m,Locator as v,LocatorText as D,getCssSelector as O,getHtmlId as I}from"@readium/shared";import{VisualNavigator as F}from"../Navigator.js";import{FramePoolManager as R}from"./frame/FramePoolManager.js";import{FXLFramePoolManager as T}from"./fxl/FXLFramePoolManager.js";import{ModuleLibrary as M,FXLModules as A,ReflowableModules as H}from"@readium/navigator-html-injectables";import{p as L}from"../_virtual/index.js";import{isTypedOMSupported as z}from"./fxl/FXLPeripherals.js";import{FrameManager as V}from"./frame/FrameManager.js";import{EpubPreferences as W}from"./preferences/EpubPreferences.js";import{EpubDefaults as N}from"./preferences/EpubDefaults.js";import{EpubPreferencesEditor as b}from"./preferences/EpubPreferencesEditor.js";import{ReadiumCSS as j}from"./css/ReadiumCSS.js";import{UserProperties as B,RSProperties as K}from"./css/Properties.js";import{getContentWidth as q}from"../helpers/dimensions.js";import{Injector as $}from"../injection/Injector.js";import{createReadiumEpubRules as G}from"../injection/epubInjectables.js";import{NavigatorProtector as X,NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as S}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as J,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as x}from"../peripherals/KeyboardPeripherals.js";import{getScriptMode as w}from"../helpers/scriptMode.js";import{EpubSettings as C}from"./preferences/EpubSettings.js";import{LineLengths as U}from"../helpers/lineLength.js";import{supportsDecorationStyle as Y,decorationsEqual as Q,resolveDecorationForWire as P}from"@readium/decorator";const Z=p=>({frameLoaded:p.frameLoaded||(()=>{}),positionChanged:p.positionChanged||(()=>{}),timelineItemChanged:p.timelineItemChanged||(()=>{}),tap:p.tap||(()=>!1),click:p.click||(()=>!1),zoom:p.zoom||(()=>{}),miscPointer:p.miscPointer||(()=>{}),scroll:p.scroll||(()=>{}),customEvent:p.customEvent||(()=>{}),handleLocator:p.handleLocator||(()=>!1),textSelected:p.textSelected||(()=>{}),contentProtection:p.contentProtection||(()=>{}),contextMenu:p.contextMenu||(()=>{}),peripheral:p.peripheral||(()=>{})});function ee(p,e){return p.length===e.length&&p.every((t,i)=>t===e[i])}class k extends F{constructor(e,t,i,s=[],o=void 0,r={preferences:{},defaults:{}}){super(),this._destroyed=!1,this._visibleFragmentIds=[],this._notifiedVisibleFragmentIds=[],this._timelineAugmented=!1,this._preferencesEditor=null,this._injector=null,this._isNavigating=!1,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._decorations=new Map,this._decorationObservers=new Map,this._decorationHoveredDecorations=new Map,this._decorationActivationState=new Map,this._decorationHoverState=new Map,this._decorationActivationConsumed=!1,this.reflowViewport={readingOrder:[],progressions:new Map,positions:null},this.pub=t,this.container=e,this.listeners=Z(i),this.currentLocation=o,s.length&&(this.positions=s),this._preferences=new W(r.preferences),this._defaults=new N(r.defaults),this._settings=new C(this._preferences,this._defaults);const h=w(t.metadata),f=h==="cjk-horizontal",n=h==="cjk-vertical",c=n||h==="mongolian-vertical",l=f||n;this._css=new j({rsProperties:new K({noVerticalPagination:c||void 0}),userProperties:new B({}),lineLengths:new U({optimalChars:this._settings.optimalLineLength,minChars:this._settings.minimalLineLength,maxChars:this._settings.maximalLineLength,padding:this._settings.scroll?(this._settings.scrollPaddingLeft||0)+(this._settings.scrollPaddingRight||0):(this._settings.pageGutter||0)*2,fontFace:this._settings.fontFamily,letterSpacing:this._settings.letterSpacing,wordSpacing:this._settings.wordSpacing,isCJK:l}),container:e,constraint:this._settings.constraint,isCJKVertical:c}),this._layout=k.determineLayout(t,!!this._settings.scroll),this.currentProgression=t.metadata.effectiveReadingProgression,this._injectablesConfig=r.injectables||{rules:[],allowedDomains:[]},this._readiumRulesPromise=G(t.metadata,t.readingOrder.items),this._contentProtection=r.contentProtection||{},this._decoratorConfig=r.decoratorConfig||{},this._decorationResizeSelectors=new Set(this._decoratorConfig.resizeWatchSelectors??[]),this._upgradeInsecureRequests=r.upgradeInsecureRequests??"always",this._keyboardPeripherals=this.mergeKeyboardPeripherals(this._contentProtection,r.keyboardPeripherals||[]),(this._contentProtection.disableContextMenu||this._contentProtection.checkAutomation||this._contentProtection.checkIFrameEmbedding||this._contentProtection.monitorDevTools||this._contentProtection.protectPrinting?.disable)&&(this._navigatorProtector=new X(this._contentProtection),this._suspiciousActivityListener=u=>{const{type:g,...y}=u.detail;g==="context_menu"?this.listeners.contextMenu(y):this.listeners.contentProtection(g,y)},window.addEventListener(S,this._suspiciousActivityListener)),this._keyboardPeripherals.length>0&&(this._keyboardPeripheralsManager=new J({keyboardPeripherals:this._keyboardPeripherals}),this._keyboardPeripheralListener=u=>{const g=u.detail;this.listeners.peripheral(g)},window.addEventListener(x,this._keyboardPeripheralListener)),this.resizeObserver=new ResizeObserver(()=>this.ownerWindow.requestAnimationFrame(async()=>await this.resizeHandler())),this.resizeObserver.observe(this.container.parentElement||document.documentElement)}static determineLayout(e,t){const i=e.metadata.effectiveLayout;if(i===d.fixed)return d.fixed;if(e.metadata.otherMetadata&&"http://openmangaformat.org/schema/1.0#version"in e.metadata.otherMetadata)return d.fixed;if(e.metadata?.conformsTo?.includes(E.DIVINA))return d.fixed;if(i===d.scrolled)return d.scrolled;const s=w(e.metadata);return s==="cjk-vertical"||s==="mongolian-vertical"?d.scrolled:i===d.reflowable&&t?d.scrolled:d.reflowable}async load(){if(this.positions?.length||(this.positions=await this.pub.positionsFromManifest()),!this._injector){const e=await this._readiumRulesPromise;this._injector=new $({rules:[...e,...this._injectablesConfig.rules],allowedDomains:this._injectablesConfig.allowedDomains})}if(!this._destroyed){if(this._layout===d.fixed)this.framePool=new T(this.container,this.positions,this.pub,this._layout,this._injector,this._contentProtection,this._keyboardPeripherals,[...this._decorationResizeSelectors],this._upgradeInsecureRequests),this.framePool.listener=(e,t)=>{this.eventListener(e,t)};else{if(await this.updateCSS(!1),this._destroyed)return;const e=this.compileCSSProperties(this._css);this.framePool=new R(this.container,this.positions,e,this._injector,this._contentProtection,this._keyboardPeripherals,t=>this.pub.timeline.segmentsForHref(t).flatMap(i=>i.references).map(i=>{const s=i.indexOf("#");return s>=0?i.slice(s+1):""}).filter(Boolean),[...this._decorationResizeSelectors],this._upgradeInsecureRequests)}if(this.currentLocation===void 0?this.currentLocation=this.positions[0]:this.currentLocation=this.completeLocator(this.currentLocation),await this.resizeHandler(),!this._destroyed)return new Promise(e=>{if(this._destroyed)return e(!1);this.go(this.currentLocation,!1,e)})}}get settings(){if(this._layout===d.fixed)return Object.freeze({...this._settings});{const e=this._css.userProperties.colCount||this._css.rsProperties.colCount||this._settings.columnCount;return Object.freeze({...this._settings,columnCount:e})}}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new b(this._preferences,this.settings,this.pub.metadata)),this._preferencesEditor}async submitPreferences(e){this._preferences=this._preferences.merging(e),await this.applyPreferences()}async applyPreferences(){const e=this._settings;this._settings=new C(this._preferences,this._defaults),this._preferencesEditor!==null&&(this._preferencesEditor=new b(this._preferences,this.settings,this.pub.metadata)),this._layout===d.fixed?this.handleFXLPrefs(e,this._settings):await this.updateCSS(!0)}handleFXLPrefs(e,t){e.columnCount!==t.columnCount&&this.framePool.setPerPage(t.columnCount)}async updateCSS(e){this._css.update(this._settings),e&&await this.commitCSS(this._css)}compileCSSProperties(e){const t={};for(const[i,s]of Object.entries(e.rsProperties.toCSSProperties()))t[i]=s;for(const[i,s]of Object.entries(e.userProperties.toCSSProperties()))t[i]=s;return t}async commitCSS(e){if(!this.framePool)return;const t=this.compileCSSProperties(e);this.framePool.setCSSProperties(t),this._css.userProperties.view==="paged"&&this._layout===d.scrolled?await this.setLayout(d.reflowable):this._css.userProperties.view==="scroll"&&this._layout===d.reflowable&&await this.setLayout(d.scrolled),this._css.setContainerWidth()}async resizeHandler(){const e=this.container.parentElement||document.documentElement;if(this._layout===d.fixed){const t=q(e)-this._settings.constraint;if(z()?this.container.attributeStyleMap.set("width",CSS.px(t)):this.container.style.width=`${t}px`,!this.framePool)return;this.framePool.resizeHandler()}else{const t=this._css.userProperties.colCount,i=this._css.userProperties.lineLength;this._css.resizeHandler(),(this._css.userProperties.view!=="scroll"&&t!==this._css.userProperties.colCount||i!==this._css.userProperties.lineLength)&&await this.commitCSS(this._css)}}get layout(){return this._layout}get ownerWindow(){return this.container.ownerDocument.defaultView||window}get _cframes(){return(this.framePool?.currentFrames??[]).filter(e=>!(e instanceof V&&e.isDestroyed))}get pool(){return this.framePool}eventListener(e,t,i){switch(e){case"_pong":if(this.listeners.frameLoaded(this._cframes[0].iframe.contentWindow),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),i){const a=this._cframes.filter(l=>!!l).indexOf(i),c=a>=0?this.viewport.readingOrder[a]:void 0;c&&this._reapplyDecorationsToFrame(i,c)}else this._reapplyDecorationsToCurrentFrames();break;case"first_visible_locator":const s=v.deserialize(t);if(!s)break;this.currentLocation=new v({href:this.currentLocation.href,type:this.currentLocation.type,title:this.currentLocation.title,locations:s?.locations,text:s?.text}),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation);break;case"text_selected":{const n=t;if(i){const c=this._cframes.filter(u=>!!u).indexOf(i),l=c>=0?this.viewport.readingOrder[c]:void 0;if(l){const u=this.pub.readingOrder.findWithHref(l);n.locator=new v({href:l,type:u.type||"application/xhtml+xml",text:new D({highlight:n.text})})}}this.listeners.textSelected(n);break}case"decoration_activated":{this._handleDecorationActivated(t)&&(this._decorationActivationConsumed=!0);break}case"decoration_pointer_enter":this._handleDecorationPointerEnter(t);break;case"decoration_pointer_leave":this._handleDecorationPointerLeave(t);break;case"click":case"tap":if(this._decorationActivationConsumed){this._decorationActivationConsumed=!1;break}const o=t;if(o.interactiveElement){const n=new DOMParser().parseFromString(o.interactiveElement,"text/html").body.children[0];if(n.nodeType===n.ELEMENT_NODE&&n.nodeName==="A"&&n.hasAttribute("href")){const a=n.attributes.getNamedItem("href")?.value;if(a.startsWith("#"))this.go(this.currentLocation.copyWithLocations({fragments:[a.substring(1)]}),!1,()=>{});else if(a.startsWith("http://")||a.startsWith("https://")||a.startsWith("mailto:")||a.startsWith("tel:"))this.listeners.handleLocator(new _({href:a}).locator);else try{this.goLink(new _({href:L.join(L.dirname(this.currentLocation.href),a)}),!1,()=>{})}catch(c){console.warn(`Couldn't go to link for ${a}: ${c}`),this.listeners.handleLocator(new _({href:a}).locator)}}else console.log("Clicked on",n)}else{if(this._layout===d.fixed&&this.framePool.doNotDisturb&&(o.doNotDisturb=!0),this._layout===d.fixed&&(this.currentProgression===m.rtl||this.currentProgression===m.ltr)&&this.framePool.currentFrames.length>1){const c=this.framePool.currentFrames;o.targetFrameSrc===c[this.currentProgression===m.rtl?0:1]?.source&&(o.x+=(c[this.currentProgression===m.rtl?1:0]?.iframe.contentWindow?.innerWidth??0)*window.devicePixelRatio)}if(e==="click"?this.listeners.click(o):this.listeners.tap(o))break;const a=(this._cframes.length===2?this._cframes[0].window.innerWidth+this._cframes[1].window.innerWidth:this._cframes[0].window.innerWidth)*window.devicePixelRatio/4;o.x>=a&&o.x<=a*3&&this.listeners.miscPointer(1),o.x<a?this.goLeft(!1,()=>{}):o.x>a*3&&this.goRight(!1,()=>{})}break;case"tap_more":this.listeners.miscPointer(t);break;case"no_more":this.changeResource(1);break;case"no_less":this.changeResource(-1);break;case"swipe":break;case"scroll":this.listeners.scroll(t);break;case"zoom":this.listeners.zoom(t);break;case"progress":this.syncLocation(t);break;case"content_protection":const r=t;this.listeners.contentProtection(r.type,r);break;case"context_menu":this.listeners.contextMenu(t);break;case"keyboard_peripherals":const h=t,f={...h,interactiveElement:void 0};h.interactiveElement&&(f.interactiveElement=new DOMParser().parseFromString(h.interactiveElement,"text/html").body.children[0]),this.listeners.peripheral(f);break;case"log":console.log(this._cframes[0]?.source?.split("/")[3],...t);break;default:this.listeners.customEvent(e,t);break}}determineModules(){let e=Array.from(M.keys());if(this._layout===d.fixed)return e.filter(s=>A.includes(s));e=e.filter(s=>H.includes(s));const t=w(this.pub.metadata);if(t==="cjk-vertical"||t==="mongolian-vertical")return e.filter(s=>s!=="column_snapper"&&s!=="scroll_snapper");const i=e;return this._layout===d.scrolled?e=i.filter(s=>s!=="column_snapper"&&s!=="cjk_vertical_snapper"):e=i.filter(s=>s!=="scroll_snapper"&&s!=="cjk_vertical_snapper"),e}attachListener(){const e=this._cframes.filter(t=>!!t);if(e.length===0)throw Error("no cframe to attach listener to");e.forEach(t=>{t.msg&&(t.msg.listener=(i,s)=>{this.eventListener(i,s,t)})}),this._reapplyDecorationsToCurrentFrames()}async apply(){if(await this.framePool.update(this.pub,this.currentLocator,this.determineModules()),this.attachListener(),this.pub.readingOrder.findIndexWithHref(this.currentLocation.href)<0)throw Error("Link for "+this.currentLocation.href+" not found!")}supportsDecorationStyle(e){return Y(e,this._decoratorConfig.decorationTemplates)}registerDecorationObserver(e,t){this._decorationObservers.has(e)||this._decorationObservers.set(e,new Set),this._decorationObservers.get(e).add(t),t.onDecorationActivated&&(this._decorationActivationState.set(e,!0),this._sendDecorationActivationToFrames(e,!0)),(t.onDecorationPointerEnter||t.onDecorationPointerLeave)&&(this._decorationHoverState.set(e,!0),this._sendDecorationHoverToFrames(e,!0))}unregisterDecorationObserver(e){this._decorationObservers.forEach((t,i)=>{if(!t.has(e))return;t.delete(e);const s=[...t].some(r=>r.onDecorationActivated);this._decorationActivationState.has(i)&&!s&&(this._decorationActivationState.delete(i),this._sendDecorationActivationToFrames(i,!1));const o=[...t].some(r=>r.onDecorationPointerEnter||r.onDecorationPointerLeave);this._decorationHoverState.has(i)&&!o&&(this._decorationHoverState.delete(i),this._sendDecorationHoverToFrames(i,!1))})}_sendDecorationActivationToFrames(e,t){this._cframes.filter(s=>!!s).forEach(s=>{s.msg&&s.msg.send("decoration_activatable",{group:e,activatable:t})})}_sendDecorationHoverToFrames(e,t){this._cframes.filter(s=>!!s).forEach(s=>{s.msg&&s.msg.send("decoration_hoverable",{group:e,hoverable:t})})}addDecorationResizeTarget(e){this._decorationResizeSelectors.add(e),this.framePool?.addResizeTarget(e)}removeDecorationResizeTarget(e){this._decorationResizeSelectors.delete(e),this.framePool?.removeResizeTarget(e)}applyDecorations(e,t){const i=this._decorations.get(t)??[],s=new Map(i.map(c=>[c.id,c])),o=new Map(e.map(c=>[c.id,c])),r=[],h=[],f=[];for(const[c,l]of s)o.has(c)?Q(l,o.get(c))||f.push(o.get(c)):r.push(c);for(const[c,l]of o)s.has(c)||h.push(l);this._decorations.set(t,e),this._sendDecorationOps(t,r,h,f,i);const n=this._decorationActivationState.get(t);n!==void 0&&this._sendDecorationActivationToFrames(t,n);const a=this._decorationHoverState.get(t);a!==void 0&&this._sendDecorationHoverToFrames(t,a)}_sendDecorationOps(e,t,i,s,o){const r=this._cframes.filter(n=>!!n),h=new Map(o.map(n=>[n.id,n])),f=this.viewport.readingOrder;r.forEach((n,a)=>{if(!n.msg)return;const c=f[a];if(c){for(const l of t){const u=h.get(l);!u||u.locator.href!==c||n.msg.send("decorate",{group:e,action:"remove",decoration:{id:l}})}for(const l of i)l.locator.href===c&&n.msg.send("decorate",{group:e,action:"add",decoration:P(l,this._decoratorConfig.decorationTemplates)});for(const l of s)l.locator.href===c&&n.msg.send("decorate",{group:e,action:"update",decoration:P(l,this._decoratorConfig.decorationTemplates)})}})}_reapplyDecorationsToFrame(e,t){if(e.msg){for(const[i,s]of this._decorations){const o=s.filter(r=>r.locator.href===t);if(o.length!==0){e.msg.send("decorate",{group:i,action:"clear"});for(const r of o)e.msg.send("decorate",{group:i,action:"add",decoration:P(r,this._decoratorConfig.decorationTemplates)})}}for(const[i,s]of this._decorationActivationState)e.msg.send("decoration_activatable",{group:i,activatable:s});for(const[i,s]of this._decorationHoverState)e.msg.send("decoration_hoverable",{group:i,hoverable:s})}}_reapplyDecorationsToCurrentFrames(){const e=this._cframes.filter(i=>!!i),t=this.viewport.readingOrder;e.forEach((i,s)=>{const o=t[s];o&&this._reapplyDecorationsToFrame(i,o)})}_handleDecorationActivated(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return!1;const i=(this._decorations.get(e.group)??[]).find(r=>r.id===e.decorationId);if(!i)return!1;const s={decoration:i,group:e.group,rect:e.rect,point:e.point};let o=!1;for(const r of t)r.onDecorationActivated?.(s)&&(o=!0);return o}_handleDecorationPointerEnter(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId);if(!i)return;this._decorationHoveredDecorations.set(e.group,i);const s={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerEnter?.(s)}_handleDecorationPointerLeave(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId)??this._decorationHoveredDecorations.get(e.group);if(this._decorationHoveredDecorations.delete(e.group),!i)return;const s={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerLeave?.(s)}async destroy(){this._destroyed=!0,this._suspiciousActivityListener&&window.removeEventListener(S,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(x,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardPeripheralsManager?.destroy(),await this.framePool?.destroy(),this._decorations.clear(),this._decorationObservers.clear(),this._decorationHoveredDecorations.clear(),this._decorationActivationState.clear(),this._decorationHoverState.clear(),this._decorationResizeSelectors.clear()}async changeResource(e){if(e===0)return!1;if(this._layout===d.fixed){const s=this.framePool,o=s.viewport.positions[0];if(e===1){if(!s.next(s.perPage))return!1}else if(e===-1){if(!s.prev(s.perPage))return!1}else throw Error("Invalid relative value for FXL");const r=s.viewport.positions[0];if(o>r){for(let h=this.positions.length-1;h>=0;h--)if(this.positions[h].href===this.pub.readingOrder.items[r-1].href){this.currentLocation=this.positions[h].copyWithLocations({progression:.999999999999});break}}else if(o<r){for(let h=0;h<this.positions.length;h++)if(this.positions[h].href===this.pub.readingOrder.items[r-1].href){this.currentLocation=this.positions[h];break}}return await this.apply(),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),!0}const t=this.pub.readingOrder.findIndexWithHref(this.currentLocation.href),i=Math.max(0,Math.min(this.pub.readingOrder.items.length-1,t+e));if(i===t)return this._cframes[0]?.msg?.send("shake",void 0,async s=>{}),!1;if(t>i){for(let s=this.positions.length-1;s>=0;s--)if(this.positions[s].href===this.pub.readingOrder.items[i].href){this.currentLocation=this.positions[s].copyWithLocations({progression:.999999999999});break}}else for(let s=0;s<this.positions.length;s++)if(this.positions[s].href===this.pub.readingOrder.items[i].href){this.currentLocation=this.positions[s];break}return await this.apply(),!0}findLastPositionInProgressionRange(e,t){const i=e.findLastIndex(s=>{const o=s.locations.progression;return!!(o&&o>t.start&&o<=t.end)});return i!==-1?e[i]:void 0}findNearestPositions(e){const t=this.positions.filter(r=>r.href===this.currentLocation.href);let i=this.currentLocation,s;const o=t.findLastIndex(r=>(r.locations.progression??0)<=e.start);if(o!==-1){i=t[o];const r=t.slice(o+1);s=this.findLastPositionInProgressionRange(r,e)}return{first:i,last:s}}updateViewport(e){this.reflowViewport.readingOrder=[],this.reflowViewport.progressions.clear(),this.reflowViewport.positions=null,this.currentLocation&&(this.reflowViewport.readingOrder.push(this.currentLocation.href),this.reflowViewport.progressions.set(this.currentLocation.href,e),this.currentLocation.locations?.position!==void 0&&(this.reflowViewport.positions=[this.currentLocation.locations.position],this.lastLocationInView?.locations?.position!==void 0&&this.reflowViewport.positions.push(this.lastLocationInView.locations.position)))}async syncLocation(e){const t=e,i=this.findNearestPositions(t);this.currentLocation=i.first.copyWithLocations({progression:t.start}),this.lastLocationInView=i.last,this.updateViewport(t),this.listeners.positionChanged(this.currentLocation);const s=t.fragmentId?this.currentLocation.copyWithLocations({fragments:[`#${t.fragmentId}`]}):this.currentLocation;this._visibleFragmentIds=t.visibleFragmentIds??[],this._notifyTimelineChange(s),await this.framePool.update(this.pub,this.currentLocation,this.determineModules())}goBackward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this._layout===d.fixed?this.changeResource(-1).then(i=>{this._isNavigating=!1,t(i)}):this._cframes[0]?.msg?.send("go_prev",void 0,async i=>{if(i)this._isNavigating=!1,t(!0);else{const s=await this.changeResource(-1);this._isNavigating=!1,t(s)}})}goForward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this._layout===d.fixed?this.changeResource(1).then(i=>{this._isNavigating=!1,t(i)}):this._cframes[0]?.msg?.send("go_next",void 0,async i=>{if(i)this._isNavigating=!1,t(!0);else{const s=await this.changeResource(1);this._isNavigating=!1,t(s)}})}get currentLocator(){return this.currentLocation}get viewport(){return this._layout===d.fixed?this.framePool?this.framePool.viewport:{readingOrder:[],progressions:new Map,positions:null}:this.reflowViewport}get isScrollStart(){const e=this.viewport.readingOrder[0];return this.viewport.progressions.get(e)?.start===0}get isScrollEnd(){const e=this.viewport.readingOrder[this.viewport.readingOrder.length-1];return this.viewport.progressions.get(e)?.end===1}get canGoBackward(){const e=this.pub.readingOrder.items[0]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.start===0)}get canGoForward(){const e=this.pub.readingOrder.items[this.pub.readingOrder.items.length-1]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.end===1)}get readingProgression(){return this.currentProgression}async setLayout(e){this._layout!==e&&(this._layout=e,await this.framePool.update(this.pub,this.currentLocator,this.determineModules(),!0),this.attachListener())}get publication(){return this.pub}get timeline(){const e=this.pub.timeline;if(!this._timelineAugmented&&this.positions?.length){const t=this.positions,i=new Set;e.augment((s,o)=>{if(s.children?.length)return{};const r=o.href.indexOf("#"),h=r>=0?o.href.slice(0,r):o.href,f=r>=0?o.href.slice(r+1):void 0,n=t.filter(l=>l.href===h);if(!n.length)return{};const a=f?n.find(l=>l.locations.fragments?.[0]===f):void 0;let c;return a?c=a:i.has(h)?c=void 0:(i.add(h),c=n.reduce((l,u)=>(u.locations.position??1/0)<(l.locations.position??1/0)?u:l)),c?{position:c.locations.position,scroll:a?.locations.progression}:{}}),this._timelineAugmented=!0}return this._wrappedTimeline||(this._wrappedTimeline=new Proxy(e,{get:(t,i)=>{if(i!=="navigableFrom"){const s=Reflect.get(t,i,t);return typeof s=="function"?s.bind(t):s}return s=>{const o=this._visibleFragmentIds;let r=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[0]}`]})):void 0)??s;const h=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[o.length-1]}`]})):void 0)??s;if(this.isScrollStart){const a=t.ancestors(r).find(c=>c.references.includes(this.currentLocation.href));a&&(r=a)}const f=t.navigableFrom(r).previous,n=t.navigableFrom(h).next;return{previous:f,next:n}}}})),this._wrappedTimeline}async loadLocator(e,t){let i=!1,s=O(e.locations);if(e.text?.highlight?i=await new Promise((f,n)=>{this._cframes[0].msg.send("go_text",s?[e.text?.serialize(),s]:e.text?.serialize(),a=>f(a))}):s&&(i=await new Promise((f,n)=>{this._cframes[0].msg.send("go_text",["",s],a=>f(a))})),i){t(i);return}const o=I(e.locations);if(o&&(i=await new Promise((f,n)=>{this._cframes[0].msg.send("go_id",o,a=>f(a))})),i){t(i);return}const r=e.locations?.progression;r&&r>0?i=await new Promise((f,n)=>{this._cframes[0].msg.send("go_progression",r,a=>f(a))}):i=!0,t(i)}completeLocator(e){if(!e.href){let t=!1;if(typeof e.locations.position=="number"){const i=this.positions.find(s=>s.locations.position===e.locations.position);i&&(e=i.copyWithLocations(e.locations),t=!0)}if(!t&&typeof e.locations?.totalProgression=="number"){const i=e.locations.totalProgression;let s=0,o=1/0;for(let r=0;r<this.positions.length;r++){const f=this.positions[r].locations.totalProgression??r/this.positions.length,n=Math.abs(f-i);n<o&&(o=n,s=r)}e=this.positions[s].copyWithLocations(e.locations)}}return e}go(e,t,i){e=this.completeLocator(e);const s=e.href.split("#")[0];let o=this.pub.readingOrder.findWithHref(s);if(!o)return i(this.listeners.handleLocator(e));if(this._isNavigating){i(!1);return}this._isNavigating=!0,this.currentLocation=this.positions.find(r=>r.href===o.href),this.apply().then(()=>this.loadLocator(e,r=>{this._isNavigating=!1,i(r)})).then(()=>{this.attachListener()}).catch(r=>{console.error(r),this._isNavigating=!1,i(!1)})}goLink(e,t,i){return this.go(e.locator,t,i)}_notifyTimelineChange(e){const t=this.timeline.locate(e),i=!ee(this._visibleFragmentIds,this._notifiedVisibleFragmentIds);(t!==this._currentTimelineItem||i)&&(this._currentTimelineItem=t,this._notifiedVisibleFragmentIds=this._visibleFragmentIds,this.listeners.timelineItemChanged(t))}}export{k as EpubNavigator};
|
|
1
|
+
import{Layout as f,Profile as O,Link as _,Locator as v,LocatorText as D,getCssSelector as w,ReadingProgression as L,getHtmlId as T}from"@readium/shared";import{VisualNavigator as F}from"../Navigator.js";import{FramePoolManager as R}from"./frame/FramePoolManager.js";import{FXLFramePoolManager as M}from"./fxl/FXLFramePoolManager.js";import{ModuleLibrary as A,FXLModules as H,ReflowableModules as W}from"@readium/navigator-html-injectables";import{p as x}from"../_virtual/index.js";import{isTypedOMSupported as N}from"./fxl/FXLPeripherals.js";import{FrameManager as g}from"./frame/FrameManager.js";import{EpubPreferences as z}from"./preferences/EpubPreferences.js";import{EpubDefaults as V}from"./preferences/EpubDefaults.js";import{EpubPreferencesEditor as k}from"./preferences/EpubPreferencesEditor.js";import{ReadiumCSS as j}from"./css/ReadiumCSS.js";import{UserProperties as q,RSProperties as B}from"./css/Properties.js";import{getContentWidth as X}from"../helpers/dimensions.js";import{Injector as K}from"../injection/Injector.js";import{createReadiumEpubRules as $}from"../injection/epubInjectables.js";import{NavigatorProtector as G,NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as S}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as U,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as C}from"../peripherals/KeyboardPeripherals.js";import{getScriptMode as y}from"../helpers/scriptMode.js";import{EpubSettings as E}from"./preferences/EpubSettings.js";import{LineLengths as J}from"../helpers/lineLength.js";import{supportsDecorationStyle as Y,decorationsEqual as Q,resolveDecorationForWire as P}from"@readium/decorator";const Z=1e3,ee=p=>({frameLoaded:p.frameLoaded||(()=>{}),positionChanged:p.positionChanged||(()=>{}),timelineItemChanged:p.timelineItemChanged||(()=>{}),tap:p.tap||(()=>!1),click:p.click||(()=>!1),zoom:p.zoom||(()=>{}),miscPointer:p.miscPointer||(()=>{}),scroll:p.scroll||(()=>{}),customEvent:p.customEvent||(()=>{}),handleLocator:p.handleLocator||(()=>!1),textSelected:p.textSelected||(()=>{}),contentProtection:p.contentProtection||(()=>{}),contextMenu:p.contextMenu||(()=>{}),peripheral:p.peripheral||(()=>{})});function te(p,e){return p.length===e.length&&p.every((t,i)=>t===e[i])}class I extends F{constructor(e,t,i,s=[],o=void 0,r={preferences:{},defaults:{}}){super(),this._destroyed=!1,this._visibleFragmentIds=[],this._notifiedVisibleFragmentIds=[],this._timelineAugmented=!1,this._preferencesEditor=null,this._injector=null,this._isNavigating=!1,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._decorations=new Map,this._decorationObservers=new Map,this._decorationHoveredDecorations=new Map,this._decorationActivationState=new Map,this._decorationHoverState=new Map,this._decorationActivationConsumed=!1,this._navigationLocked=!1,this._pointedPieceRequests=new Map,this._pointedPieceRequestId=0,this.reflowViewport={readingOrder:[],progressions:new Map,positions:null},this.pub=t,this.container=e,this.listeners=ee(i),this.currentLocation=o,s.length&&(this.positions=s),this._preferences=new z(r.preferences),this._defaults=new V(r.defaults),this._settings=new E(this._preferences,this._defaults);const h=y(t.metadata),d=h==="cjk-horizontal",a=h==="cjk-vertical",c=a||h==="mongolian-vertical",l=d||a;this._css=new j({rsProperties:new B({noVerticalPagination:c||void 0}),userProperties:new q({}),lineLengths:new J({optimalChars:this._settings.optimalLineLength,minChars:this._settings.minimalLineLength,maxChars:this._settings.maximalLineLength,padding:this._settings.scroll?(this._settings.scrollPaddingLeft||0)+(this._settings.scrollPaddingRight||0):(this._settings.pageGutter||0)*2,fontFace:this._settings.fontFamily,letterSpacing:this._settings.letterSpacing,wordSpacing:this._settings.wordSpacing,isCJK:l}),container:e,constraint:this._settings.constraint,isCJKVertical:c}),this._layout=I.determineLayout(t,!!this._settings.scroll),this.currentProgression=t.metadata.effectiveReadingProgression,this._injectablesConfig=r.injectables||{rules:[],allowedDomains:[]},this._readiumRulesPromise=$(t.metadata,t.readingOrder.items),this._contentProtection=r.contentProtection||{},this._decoratorConfig=r.decoratorConfig||{},this._decorationResizeSelectors=new Set(this._decoratorConfig.resizeWatchSelectors??[]),this._upgradeInsecureRequests=r.upgradeInsecureRequests??"always",this._keyboardPeripherals=this.mergeKeyboardPeripherals(this._contentProtection,r.keyboardPeripherals||[]),(this._contentProtection.disableContextMenu||this._contentProtection.checkAutomation||this._contentProtection.checkIFrameEmbedding||this._contentProtection.monitorDevTools||this._contentProtection.protectPrinting?.disable)&&(this._navigatorProtector=new G(this._contentProtection),this._suspiciousActivityListener=u=>{const{type:m,...b}=u.detail;m==="context_menu"?this.listeners.contextMenu(b):this.listeners.contentProtection(m,b)},window.addEventListener(S,this._suspiciousActivityListener)),this._keyboardPeripherals.length>0&&(this._keyboardPeripheralsManager=new U({keyboardPeripherals:this._keyboardPeripherals}),this._keyboardPeripheralListener=u=>{const m=u.detail;this.listeners.peripheral(m)},window.addEventListener(C,this._keyboardPeripheralListener)),this.resizeObserver=new ResizeObserver(()=>this.ownerWindow.requestAnimationFrame(async()=>await this.resizeHandler())),this.resizeObserver.observe(this.container.parentElement||document.documentElement)}static determineLayout(e,t){const i=e.metadata.effectiveLayout;if(i===f.fixed)return f.fixed;if(e.metadata.otherMetadata&&"http://openmangaformat.org/schema/1.0#version"in e.metadata.otherMetadata)return f.fixed;if(e.metadata?.conformsTo?.includes(O.DIVINA))return f.fixed;if(i===f.scrolled)return f.scrolled;const s=y(e.metadata);return s==="cjk-vertical"||s==="mongolian-vertical"?f.scrolled:i===f.reflowable&&t?f.scrolled:f.reflowable}async load(){if(this.positions?.length||(this.positions=await this.pub.positionsFromManifest()),!this._injector){const e=await this._readiumRulesPromise;this._injector=new K({rules:[...e,...this._injectablesConfig.rules],allowedDomains:this._injectablesConfig.allowedDomains})}if(!this._destroyed){if(this._layout===f.fixed)this.framePool=new M(this.container,this.positions,this.pub,this._layout,this._injector,this._contentProtection,this._keyboardPeripherals,[...this._decorationResizeSelectors],this._upgradeInsecureRequests),this.framePool.listener=(e,t)=>{this.eventListener(e,t)};else{if(await this.updateCSS(!1),this._destroyed)return;const e=this.compileCSSProperties(this._css);this.framePool=new R(this.container,this.positions,e,this._injector,this._contentProtection,this._keyboardPeripherals,t=>this.pub.timeline.segmentsForHref(t).flatMap(i=>i.references).map(i=>{const s=i.indexOf("#");return s>=0?i.slice(s+1):""}).filter(Boolean),[...this._decorationResizeSelectors],this._upgradeInsecureRequests)}if(this.currentLocation===void 0?this.currentLocation=this.positions[0]:this.currentLocation=this.completeLocator(this.currentLocation),await this.resizeHandler(),!this._destroyed)return new Promise(e=>{if(this._destroyed)return e(!1);this.go(this.currentLocation,!1,e)})}}get settings(){if(this._layout===f.fixed)return Object.freeze({...this._settings});{const e=this._css.userProperties.colCount||this._css.rsProperties.colCount||this._settings.columnCount;return Object.freeze({...this._settings,columnCount:e})}}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new k(this._preferences,this.settings,this.pub.metadata)),this._preferencesEditor}async submitPreferences(e){this._preferences=this._preferences.merging(e),await this.applyPreferences()}async applyPreferences(){const e=this._settings;this._settings=new E(this._preferences,this._defaults),this._preferencesEditor!==null&&(this._preferencesEditor=new k(this._preferences,this.settings,this.pub.metadata)),this._layout===f.fixed?this.handleFXLPrefs(e,this._settings):await this.updateCSS(!0)}handleFXLPrefs(e,t){e.columnCount!==t.columnCount&&this.framePool.setPerPage(t.columnCount)}async updateCSS(e){this._css.update(this._settings),e&&await this.commitCSS(this._css)}compileCSSProperties(e){const t={};for(const[i,s]of Object.entries(e.rsProperties.toCSSProperties()))t[i]=s;for(const[i,s]of Object.entries(e.userProperties.toCSSProperties()))t[i]=s;return t}async commitCSS(e){if(!this.framePool)return;const t=this.compileCSSProperties(e);this.framePool.setCSSProperties(t),this._css.userProperties.view==="paged"&&this._layout===f.scrolled?await this.setLayout(f.reflowable):this._css.userProperties.view==="scroll"&&this._layout===f.reflowable&&await this.setLayout(f.scrolled),this._css.setContainerWidth()}async resizeHandler(){const e=this.container.parentElement||document.documentElement;if(this._layout===f.fixed){const t=X(e)-this._settings.constraint;if(N()?this.container.attributeStyleMap.set("width",CSS.px(t)):this.container.style.width=`${t}px`,!this.framePool)return;this.framePool.resizeHandler()}else{const t=this._css.userProperties.colCount,i=this._css.userProperties.lineLength;this._css.resizeHandler(),(this._css.userProperties.view!=="scroll"&&t!==this._css.userProperties.colCount||i!==this._css.userProperties.lineLength)&&await this.commitCSS(this._css)}}get layout(){return this._layout}get ownerWindow(){return this.container.ownerDocument.defaultView||window}get _cframes(){return(this.framePool?.currentFrames??[]).filter(e=>!(e instanceof g&&e.isDestroyed))}get pool(){return this.framePool}eventListener(e,t,i){switch(e){case"_pong":if(this.listeners.frameLoaded(this._cframes[0].iframe.contentWindow),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),i){const n=this._cframes.filter(l=>!!l).indexOf(i),c=n>=0?this.viewport.readingOrder[n]:void 0;c&&this._reapplyDecorationsToFrame(i,c)}else this._reapplyDecorationsToCurrentFrames();this._watchTextLayoutInCurrentFrame(!0),this._sendNavigationLock();break;case"text_layout":i&&i===this._textLayoutFrame&&this.currentLocation.href.split("#")[0]===this._textLayoutWatch?.href&&this._textLayoutWatch.cb(t);break;case"pointed_piece":{const{id:a,index:n}=t;this._pointedPieceRequests.get(a)?.(n);break}case"first_visible_locator":const s=v.deserialize(t);if(!s)break;this.currentLocation=new v({href:this.currentLocation.href,type:this.currentLocation.type,title:this.currentLocation.title,locations:s?.locations,text:s?.text}),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation);break;case"text_selected":{const a=t;if(i){const c=this._cframes.filter(u=>!!u).indexOf(i),l=c>=0?this.viewport.readingOrder[c]:void 0;if(l){const u=this.pub.readingOrder.findWithHref(l);a.locator=new v({href:l,type:u.type||"application/xhtml+xml",text:new D({highlight:a.text})})}}this.listeners.textSelected(a);break}case"decoration_activated":{this._handleDecorationActivated(t)&&(this._decorationActivationConsumed=!0);break}case"decoration_pointer_enter":this._handleDecorationPointerEnter(t);break;case"decoration_pointer_leave":this._handleDecorationPointerLeave(t);break;case"click":case"tap":if(this._decorationActivationConsumed){this._decorationActivationConsumed=!1;break}const o=t;if(o.interactiveElement){const a=new DOMParser().parseFromString(o.interactiveElement,"text/html").body.children[0];if(a.nodeType===a.ELEMENT_NODE&&a.nodeName==="A"&&a.hasAttribute("href")){const n=a.attributes.getNamedItem("href")?.value;if(n.startsWith("#"))this._navigationLocked||this.go(this.currentLocation.copyWithLocations({fragments:[n.substring(1)]}),!1,()=>{});else if(n.startsWith("http://")||n.startsWith("https://")||n.startsWith("mailto:")||n.startsWith("tel:"))this.listeners.handleLocator(new _({href:n}).locator);else if(!this._navigationLocked)try{this.goLink(new _({href:x.join(x.dirname(this.currentLocation.href),n)}),!1,()=>{})}catch(c){console.warn(`Couldn't go to link for ${n}: ${c}`),this.listeners.handleLocator(new _({href:n}).locator)}}else console.log("Clicked on",a)}else{if(this._layout===f.fixed&&this.framePool.doNotDisturb&&(o.doNotDisturb=!0),o.x+=this._spreadOffsetX(o.targetFrameSrc),e==="click"?this.listeners.click(o):this.listeners.tap(o))break;const n=(this._cframes.length===2?this._cframes[0].window.innerWidth+this._cframes[1].window.innerWidth:this._cframes[0].window.innerWidth)*window.devicePixelRatio/4;if(o.x>=n&&o.x<=n*3&&this.listeners.miscPointer(1),this._navigationLocked)break;o.x<n?this.goLeft(!1,()=>{}):o.x>n*3&&this.goRight(!1,()=>{})}break;case"tap_more":this.listeners.miscPointer(t);break;case"no_more":this._navigationLocked||this.changeResource(1);break;case"no_less":this._navigationLocked||this.changeResource(-1);break;case"swipe":break;case"scroll":this.listeners.scroll(t);break;case"zoom":this.listeners.zoom(t);break;case"progress":{const a=i instanceof g?this.framePool._frameFor(this.currentLocation.href.split("#")[0]):void 0;if(i instanceof g&&i!==a)break;this.syncLocation(t);break}case"content_protection":const r=t;this.listeners.contentProtection(r.type,r);break;case"context_menu":this.listeners.contextMenu(t);break;case"keyboard_peripherals":const h=t,d={...h,interactiveElement:void 0};h.interactiveElement&&(d.interactiveElement=new DOMParser().parseFromString(h.interactiveElement,"text/html").body.children[0]),this.listeners.peripheral(d);break;case"log":console.log(this._cframes[0]?.source?.split("/")[3],...t);break;default:this.listeners.customEvent(e,t);break}}determineModules(){let e=Array.from(A.keys());if(this._layout===f.fixed)return e.filter(s=>H.includes(s));e=e.filter(s=>W.includes(s));const t=y(this.pub.metadata);if(t==="cjk-vertical"||t==="mongolian-vertical")return e.filter(s=>s!=="column_snapper"&&s!=="scroll_snapper");const i=e;return this._layout===f.scrolled?e=i.filter(s=>s!=="column_snapper"&&s!=="cjk_vertical_snapper"):e=i.filter(s=>s!=="scroll_snapper"&&s!=="cjk_vertical_snapper"),e}attachListener(){const e=this._cframes.filter(t=>!!t);if(e.length===0)throw Error("no cframe to attach listener to");e.forEach(t=>{t.msg&&(t.msg.listener=(i,s)=>{this.eventListener(i,s,t)})}),this._reapplyDecorationsToCurrentFrames(),this._watchTextLayoutInCurrentFrame(),this._sendNavigationLock()}async apply(){if(await this.framePool.update(this.pub,this.currentLocator,this.determineModules()),this.attachListener(),this.pub.readingOrder.findIndexWithHref(this.currentLocation.href)<0)throw Error("Link for "+this.currentLocation.href+" not found!")}supportsDecorationStyle(e){return Y(e,this._decoratorConfig.decorationTemplates)}registerDecorationObserver(e,t){this._decorationObservers.has(e)||this._decorationObservers.set(e,new Set),this._decorationObservers.get(e).add(t),t.onDecorationActivated&&(this._decorationActivationState.set(e,!0),this._sendDecorationActivationToFrames(e,!0)),(t.onDecorationPointerEnter||t.onDecorationPointerLeave)&&(this._decorationHoverState.set(e,!0),this._sendDecorationHoverToFrames(e,!0))}unregisterDecorationObserver(e){this._decorationObservers.forEach((t,i)=>{if(!t.has(e))return;t.delete(e);const s=[...t].some(r=>r.onDecorationActivated);this._decorationActivationState.has(i)&&!s&&(this._decorationActivationState.delete(i),this._sendDecorationActivationToFrames(i,!1));const o=[...t].some(r=>r.onDecorationPointerEnter||r.onDecorationPointerLeave);this._decorationHoverState.has(i)&&!o&&(this._decorationHoverState.delete(i),this._sendDecorationHoverToFrames(i,!1))})}_sendDecorationActivationToFrames(e,t){this._cframes.filter(s=>!!s).forEach(s=>{s.msg&&s.msg.send("decoration_activatable",{group:e,activatable:t})})}_sendDecorationHoverToFrames(e,t){this._cframes.filter(s=>!!s).forEach(s=>{s.msg&&s.msg.send("decoration_hoverable",{group:e,hoverable:t})})}addDecorationResizeTarget(e){this._decorationResizeSelectors.add(e),this.framePool?.addResizeTarget(e)}removeDecorationResizeTarget(e){this._decorationResizeSelectors.delete(e),this.framePool?.removeResizeTarget(e)}applyDecorations(e,t){const i=this._decorations.get(t)??[],s=new Map(i.map(c=>[c.id,c])),o=new Map(e.map(c=>[c.id,c])),r=[],h=[],d=[];for(const[c,l]of s)o.has(c)?Q(l,o.get(c))||d.push(o.get(c)):r.push(c);for(const[c,l]of o)s.has(c)||h.push(l);this._decorations.set(t,e),this._sendDecorationOps(t,r,h,d,i);const a=this._decorationActivationState.get(t);a!==void 0&&this._sendDecorationActivationToFrames(t,a);const n=this._decorationHoverState.get(t);n!==void 0&&this._sendDecorationHoverToFrames(t,n)}_sendDecorationOps(e,t,i,s,o){const r=this._cframes.filter(a=>!!a),h=new Map(o.map(a=>[a.id,a])),d=this.viewport.readingOrder;r.forEach((a,n)=>{if(!a.msg)return;const c=d[n];if(c){for(const l of t){const u=h.get(l);!u||u.locator.href!==c||a.msg.send("decorate",{group:e,action:"remove",decoration:{id:l}})}for(const l of i)l.locator.href===c&&a.msg.send("decorate",{group:e,action:"add",decoration:P(l,this._decoratorConfig.decorationTemplates)});for(const l of s)l.locator.href===c&&a.msg.send("decorate",{group:e,action:"update",decoration:P(l,this._decoratorConfig.decorationTemplates)})}})}_reapplyDecorationsToFrame(e,t){if(e.msg){for(const[i,s]of this._decorations){const o=s.filter(r=>r.locator.href===t);if(o.length!==0){e.msg.send("decorate",{group:i,action:"clear"});for(const r of o)e.msg.send("decorate",{group:i,action:"add",decoration:P(r,this._decoratorConfig.decorationTemplates)})}}for(const[i,s]of this._decorationActivationState)e.msg.send("decoration_activatable",{group:i,activatable:s});for(const[i,s]of this._decorationHoverState)e.msg.send("decoration_hoverable",{group:i,hoverable:s})}}_reapplyDecorationsToCurrentFrames(){const e=this._cframes.filter(i=>!!i),t=this.viewport.readingOrder;e.forEach((i,s)=>{const o=t[s];o&&this._reapplyDecorationsToFrame(i,o)})}watchTextLayout(e,t){const i={href:e[0]?.href.split("#")[0]??"",pieces:e.map(s=>[s.text?.serialize(),w(s.locations)]),cb:t};return this._textLayoutWatch=i,this._watchTextLayoutInCurrentFrame(!0),()=>{this._textLayoutWatch===i&&(this._textLayoutWatch=void 0,this._watchTextLayoutInCurrentFrame())}}lockNavigation(e){this._navigationLocked=e,this._sendNavigationLock()}_sendNavigationLock(){this._cframes.forEach(e=>{e instanceof g&&e.msg?.send("lock_navigation",this._navigationLocked)})}_spreadOffsetX(e){if(this._layout!==f.fixed||this.currentProgression!==L.rtl&&this.currentProgression!==L.ltr)return 0;const t=this.framePool.currentFrames;if(t.length<2)return 0;const i=this.currentProgression===L.rtl;return e!==t[i?0:1]?.source?0:(t[i?1:0]?.iframe.contentWindow?.innerWidth??0)*window.devicePixelRatio}async findPointedPiece(e,t){const i=this._cframes.filter(n=>!!n),s=i.findIndex(n=>n.source===e.targetFrameSrc),o=s>=0?this.viewport.readingOrder[s]:void 0;if(!o||!e.cssSelector)return;const r=t.filter(n=>n.href.split("#")[0]===o);if(r.length===0)return;const h=`${++this._pointedPieceRequestId}`;let d;const a=await new Promise(n=>{this._pointedPieceRequests.set(h,n),d=setTimeout(()=>n(-1),Z);const c={id:h,cssSelector:e.cssSelector,x:e.x-this._spreadOffsetX(e.targetFrameSrc),y:e.y,pieces:r.map(u=>[u.text?.serialize(),w(u.locations)])};i[s].msg?.send("pointed_piece",c,()=>n(-1))||n(-1)});return clearTimeout(d),this._pointedPieceRequests.delete(h),r[a]}_watchTextLayoutInCurrentFrame(e=!1){const t=this._cframes[0],i=this._textLayoutWatch,s=i&&t instanceof g&&this.currentLocation?.href.split("#")[0]===i.href?t:void 0;if(s===this._textLayoutFrame&&!e)return;const o=this._textLayoutFrame;o&&o!==s&&!o.isDestroyed&&o.msg?.send("watch_text_layout",[]),this._textLayoutFrame=s,s&&i&&s.msg?.send("watch_text_layout",i.pieces)}_handleDecorationActivated(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return!1;const i=(this._decorations.get(e.group)??[]).find(r=>r.id===e.decorationId);if(!i)return!1;const s={decoration:i,group:e.group,rect:e.rect,point:e.point};let o=!1;for(const r of t)r.onDecorationActivated?.(s)&&(o=!0);return o}_handleDecorationPointerEnter(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId);if(!i)return;this._decorationHoveredDecorations.set(e.group,i);const s={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerEnter?.(s)}_handleDecorationPointerLeave(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId)??this._decorationHoveredDecorations.get(e.group);if(this._decorationHoveredDecorations.delete(e.group),!i)return;const s={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerLeave?.(s)}async destroy(){this._destroyed=!0,this._suspiciousActivityListener&&window.removeEventListener(S,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(C,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardPeripheralsManager?.destroy(),await this.framePool?.destroy(),this._decorations.clear(),this._decorationObservers.clear(),this._decorationHoveredDecorations.clear(),this._decorationActivationState.clear(),this._decorationHoverState.clear(),this._decorationResizeSelectors.clear()}async changeResource(e){if(e===0)return!1;if(this._layout===f.fixed){const s=this.framePool,o=s.viewport.positions[0];if(e===1){if(!s.next(s.perPage))return!1}else if(e===-1){if(!s.prev(s.perPage))return!1}else throw Error("Invalid relative value for FXL");const r=s.viewport.positions[0];if(o>r){for(let h=this.positions.length-1;h>=0;h--)if(this.positions[h].href===this.pub.readingOrder.items[r-1].href){this.currentLocation=this.positions[h].copyWithLocations({progression:.999999999999});break}}else if(o<r){for(let h=0;h<this.positions.length;h++)if(this.positions[h].href===this.pub.readingOrder.items[r-1].href){this.currentLocation=this.positions[h];break}}return await this.apply(),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),!0}const t=this.pub.readingOrder.findIndexWithHref(this.currentLocation.href),i=Math.max(0,Math.min(this.pub.readingOrder.items.length-1,t+e));if(i===t)return this._cframes[0]?.msg?.send("shake",void 0,async s=>{}),!1;if(t>i){for(let s=this.positions.length-1;s>=0;s--)if(this.positions[s].href===this.pub.readingOrder.items[i].href){this.currentLocation=this.positions[s].copyWithLocations({progression:.999999999999});break}}else for(let s=0;s<this.positions.length;s++)if(this.positions[s].href===this.pub.readingOrder.items[i].href){this.currentLocation=this.positions[s];break}return await this.apply(),!0}findLastPositionInProgressionRange(e,t){const i=e.findLastIndex(s=>{const o=s.locations.progression;return!!(o&&o>t.start&&o<=t.end)});return i!==-1?e[i]:void 0}findNearestPositions(e){const t=this.positions.filter(r=>r.href===this.currentLocation.href);let i=this.currentLocation,s;const o=t.findLastIndex(r=>(r.locations.progression??0)<=e.start);if(o!==-1){i=t[o];const r=t.slice(o+1);s=this.findLastPositionInProgressionRange(r,e)}return{first:i,last:s}}updateViewport(e){this.reflowViewport.readingOrder=[],this.reflowViewport.progressions.clear(),this.reflowViewport.positions=null,this.currentLocation&&(this.reflowViewport.readingOrder.push(this.currentLocation.href),this.reflowViewport.progressions.set(this.currentLocation.href,e),this.currentLocation.locations?.position!==void 0&&(this.reflowViewport.positions=[this.currentLocation.locations.position],this.lastLocationInView?.locations?.position!==void 0&&this.reflowViewport.positions.push(this.lastLocationInView.locations.position)))}async syncLocation(e){const t=e,i=this.findNearestPositions(t);this.currentLocation=i.first.copyWithLocations({progression:t.start}),this.lastLocationInView=i.last,this.updateViewport(t),this.listeners.positionChanged(this.currentLocation);const s=t.fragmentId?this.currentLocation.copyWithLocations({fragments:[`#${t.fragmentId}`]}):this.currentLocation;this._visibleFragmentIds=t.visibleFragmentIds??[],this._notifyTimelineChange(s),await this.framePool.update(this.pub,this.currentLocation,this.determineModules())}goBackward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this._layout===f.fixed?this.changeResource(-1).then(i=>{this._isNavigating=!1,t(i)}):this._cframes[0]?.msg?.send("go_prev",void 0,async i=>{if(i)this._isNavigating=!1,t(!0);else{const s=await this.changeResource(-1);this._isNavigating=!1,t(s)}})}goForward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this._layout===f.fixed?this.changeResource(1).then(i=>{this._isNavigating=!1,t(i)}):this._cframes[0]?.msg?.send("go_next",void 0,async i=>{if(i)this._isNavigating=!1,t(!0);else{const s=await this.changeResource(1);this._isNavigating=!1,t(s)}})}get currentLocator(){return this.currentLocation}get viewport(){return this._layout===f.fixed?this.framePool?this.framePool.viewport:{readingOrder:[],progressions:new Map,positions:null}:this.reflowViewport}get isScrollStart(){const e=this.viewport.readingOrder[0];return this.viewport.progressions.get(e)?.start===0}get isScrollEnd(){const e=this.viewport.readingOrder[this.viewport.readingOrder.length-1];return this.viewport.progressions.get(e)?.end===1}get canGoBackward(){const e=this.pub.readingOrder.items[0]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.start===0)}get canGoForward(){const e=this.pub.readingOrder.items[this.pub.readingOrder.items.length-1]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.end===1)}get readingProgression(){return this.currentProgression}async setLayout(e){this._layout!==e&&(this._layout=e,await this.framePool.update(this.pub,this.currentLocator,this.determineModules(),!0),this.attachListener())}get publication(){return this.pub}get timeline(){const e=this.pub.timeline;if(!this._timelineAugmented&&this.positions?.length){const t=this.positions,i=new Set;e.augment((s,o)=>{if(s.children?.length)return{};const r=o.href.indexOf("#"),h=r>=0?o.href.slice(0,r):o.href,d=r>=0?o.href.slice(r+1):void 0,a=t.filter(l=>l.href===h);if(!a.length)return{};const n=d?a.find(l=>l.locations.fragments?.[0]===d):void 0;let c;return n?c=n:i.has(h)?c=void 0:(i.add(h),c=a.reduce((l,u)=>(u.locations.position??1/0)<(l.locations.position??1/0)?u:l)),c?{position:c.locations.position,scroll:n?.locations.progression}:{}}),this._timelineAugmented=!0}return this._wrappedTimeline||(this._wrappedTimeline=new Proxy(e,{get:(t,i)=>{if(i!=="navigableFrom"){const s=Reflect.get(t,i,t);return typeof s=="function"?s.bind(t):s}return s=>{const o=this._visibleFragmentIds;let r=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[0]}`]})):void 0)??s;const h=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[o.length-1]}`]})):void 0)??s;if(this.isScrollStart){const n=t.ancestors(r).find(c=>c.references.includes(this.currentLocation.href));n&&(r=n)}const d=t.navigableFrom(r).previous,a=t.navigableFrom(h).next;return{previous:d,next:a}}}})),this._wrappedTimeline}async loadLocator(e,t){let i=!1,s=w(e.locations);if(e.text?.highlight?i=await new Promise((d,a)=>{this._cframes[0].msg.send("go_text",s?[e.text?.serialize(),s]:e.text?.serialize(),n=>d(n))}):s&&(i=await new Promise((d,a)=>{this._cframes[0].msg.send("go_text",["",s],n=>d(n))})),i){t(i);return}const o=T(e.locations);if(o&&(i=await new Promise((d,a)=>{this._cframes[0].msg.send("go_id",o,n=>d(n))})),i){t(i);return}const r=e.locations?.progression;r&&r>0?i=await new Promise((d,a)=>{this._cframes[0].msg.send("go_progression",r,n=>d(n))}):i=!0,t(i)}completeLocator(e){if(!e.href){let t=!1;if(typeof e.locations.position=="number"){const i=this.positions.find(s=>s.locations.position===e.locations.position);i&&(e=i.copyWithLocations(e.locations),t=!0)}if(!t&&typeof e.locations?.totalProgression=="number"){const i=e.locations.totalProgression;let s=0,o=1/0;for(let r=0;r<this.positions.length;r++){const d=this.positions[r].locations.totalProgression??r/this.positions.length,a=Math.abs(d-i);a<o&&(o=a,s=r)}e=this.positions[s].copyWithLocations(e.locations)}}return e}go(e,t,i){e=this.completeLocator(e);const s=e.href.split("#")[0];let o=this.pub.readingOrder.findWithHref(s);if(!o)return i(this.listeners.handleLocator(e));if(this._isNavigating){i(!1);return}this._isNavigating=!0,this.currentLocation=this.positions.find(r=>r.href===o.href),this.apply().then(()=>this.loadLocator(e,r=>{this._isNavigating=!1,i(r)})).then(()=>{this.attachListener()}).catch(r=>{console.error(r),this._isNavigating=!1,i(!1)})}goLink(e,t,i){return this.go(e.locator,t,i)}_notifyTimelineChange(e){const t=this.timeline.locate(e),i=!te(this._visibleFragmentIds,this._notifiedVisibleFragmentIds);(t!==this._currentTimelineItem||i)&&(this._currentTimelineItem=t,this._notifiedVisibleFragmentIds=this._visibleFragmentIds,this.listeners.timelineItemChanged(t))}}export{I as EpubNavigator};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import P from"./FrameBlobBuilder.js";import{FrameManager as U}from"./FrameManager.js";const w=10,y=5;class F{constructor(e,i,s,c,h,r,n,p=[],o){this.pool=new Map,this.blobs=new Map,this.inprogress=new Map,this.pendingUpdates=new Map,this.injector=null,this.updateSequence=0,this.container=e,this.positions=i,this.currentCssProperties=s,this.injector=c??null,this.contentProtectionConfig=h||{},this.keyboardPeripheralsConfig=r||[],this.getFragmentIds=n??(()=>[]),this.resizeWatchSelectors=[...p],this.upgradeInsecureRequests=o??"always"}addResizeTarget(e){this.resizeWatchSelectors.includes(e)||this.resizeWatchSelectors.push(e),this.pool.forEach(i=>i.addResizeTarget(e))}removeResizeTarget(e){this.resizeWatchSelectors=this.resizeWatchSelectors.filter(i=>i!==e),this.pool.forEach(i=>i.removeResizeTarget(e))}async destroy(){let e=this.inprogress.values(),i=e.next();const s=[];for(;i.value;)s.push(i.value),i=e.next();s.length>0&&await Promise.allSettled(s),this.inprogress.clear();let c=this.pool.values(),h=c.next();for(;h.value;)await h.value.destroy(),h=c.next();this.pool.clear(),this.blobs.forEach(r=>r.reset()),this.blobs.clear(),this.injector?.dispose(),this.container.childNodes.forEach(r=>{(r.nodeType===Node.ELEMENT_NODE||r.nodeType===Node.TEXT_NODE)&&r.remove()})}async update(e,i,s,c=!1){for(;this.forcedUpdate;)await this.forcedUpdate;const h=++this.updateSequence;let r=this.positions.findIndex(o=>o.locations.position===i.locations.position);if(r<0)throw Error(`Locator not found in position list: ${i.locations.position} > ${this.positions.reduce((o,g)=>g.locations.position||0>o?g.locations.position||0:o,0)}`);const n=this.positions[r].href;this.inprogress.has(n)&&await this.inprogress.get(n);const p=new Promise(async(o,g)=>{const m=[],d=[];this.positions.forEach((t,a)=>{(a>r+w||a<r-w)&&(m.includes(t.href)||m.push(t.href)),a<r+y&&a>r-y&&(d.includes(t.href)||d.push(t.href))}),m.forEach(async t=>{d.includes(t)||this.pool.has(t)&&(await this.pool.get(t)?.destroy(),this.pool.delete(t),this.pendingUpdates.has(t)&&this.pendingUpdates.set(t,{inPool:!1}))}),this.currentBaseURL!==void 0&&e.baseURL!==this.currentBaseURL&&(this.blobs.forEach(t=>t.reset()),this.blobs.clear()),this.currentBaseURL=e.baseURL,c&&(this.blobs.forEach(t=>t.reset()),this.blobs.clear(),this.pendingUpdates.clear());const b=async t=>{if(this.pendingUpdates.has(t)&&this.pendingUpdates.get(t)?.inPool===!1){const f=this.blobs.get(t);f&&(f.reset(),this.blobs.delete(t),this.pendingUpdates.delete(t))}if(this.pool.has(t)){const f=this.pool.get(t);if(!this.blobs.has(t))await f.destroy(),this.pool.delete(t),this.pendingUpdates.delete(t);else{await f.load(s);return}}const a=e.readingOrder.findWithHref(t);if(!a)return;this.blobs.has(t)||this.blobs.set(t,new P(e,this.currentBaseURL||"",a,{cssProperties:this.currentCssProperties,injector:this.injector,upgradeInsecureRequests:this.upgradeInsecureRequests}));const l=new U(await this.blobs.get(t).build(),this.contentProtectionConfig,this.keyboardPeripheralsConfig,this.getFragmentIds(t),this.resizeWatchSelectors);return t!==n&&await l.hide(),this.container.appendChild(l.iframe),await l.load(s),this.pool.set(t,l),l};try{await Promise.all(d.filter(t=>t===n).map(t=>b(t)))}catch(t){g(t);return}if(h!==this.updateSequence){o();return}Promise.all(d.filter(t=>t!==n&&!this.inprogress.has(t)).map(async t=>{const a=b(t);this.inprogress.set(t,a);try{await a}finally{this.inprogress.get(t)===a&&this.inprogress.delete(t)}})).catch(t=>console.warn("Failed preloading frame",t));const u=this.pool.get(n);if(!u){o();return}if(u?.source!==this._currentFrame?.source||c){if(await this._currentFrame?.hide(),h!==this.updateSequence){o();return}const t=this.pool.get(n);if(!t){o();return}if(await t.load(s),h!==this.updateSequence){o();return}const a=this.pool.get(n);if(!a){o();return}if(await a.show(i.locations.progression),this._currentFrame=a,u){const l=this.container.ownerDocument.activeElement;l&&l.tagName==="IFRAME"&&l!==u.iframe&&u.iframe.focus({preventScroll:!0})}}o()});if(this.inprogress.set(n,p),c){const o=p.catch(()=>{});this.forcedUpdate=o,o.then(()=>{this.forcedUpdate===o&&(this.forcedUpdate=void 0)})}try{await p}finally{this.inprogress.delete(n)}}setCSSProperties(e){if(!((s,c)=>{const h=Object.keys(s),r=Object.keys(c);if(h.length!==r.length)return!1;for(const n of h)if(s[n]!==c[n])return!1;return!0})(this.currentCssProperties||{},e)){this.currentCssProperties=e,this.pool.forEach(s=>{s.setCSSProperties(e)});for(const s of this.blobs.keys())this.pendingUpdates.set(s,{inPool:this.pool.has(s)})}}get currentFrames(){return[this._currentFrame]}get currentBounds(){const e={x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0,toJSON(){return this}};return this.currentFrames.forEach(i=>{if(!i)return;const s=i.realSize;e.x=Math.min(e.x,s.x),e.y=Math.min(e.y,s.y),e.width+=s.width,e.height=Math.max(e.height,s.height),e.top=Math.min(e.top,s.top),e.right=Math.min(e.right,s.right),e.bottom=Math.min(e.bottom,s.bottom),e.left=Math.min(e.left,s.left)}),e}}export{F as FramePoolManager};
|
|
1
|
+
import P from"./FrameBlobBuilder.js";import{FrameManager as U}from"./FrameManager.js";const w=10,y=5;class F{constructor(e,i,s,c,h,r,n,p=[],o){this.pool=new Map,this.blobs=new Map,this.inprogress=new Map,this.pendingUpdates=new Map,this.injector=null,this.updateSequence=0,this.container=e,this.positions=i,this.currentCssProperties=s,this.injector=c??null,this.contentProtectionConfig=h||{},this.keyboardPeripheralsConfig=r||[],this.getFragmentIds=n??(()=>[]),this.resizeWatchSelectors=[...p],this.upgradeInsecureRequests=o??"always"}addResizeTarget(e){this.resizeWatchSelectors.includes(e)||this.resizeWatchSelectors.push(e),this.pool.forEach(i=>i.addResizeTarget(e))}removeResizeTarget(e){this.resizeWatchSelectors=this.resizeWatchSelectors.filter(i=>i!==e),this.pool.forEach(i=>i.removeResizeTarget(e))}async destroy(){let e=this.inprogress.values(),i=e.next();const s=[];for(;i.value;)s.push(i.value),i=e.next();s.length>0&&await Promise.allSettled(s),this.inprogress.clear();let c=this.pool.values(),h=c.next();for(;h.value;)await h.value.destroy(),h=c.next();this.pool.clear(),this.blobs.forEach(r=>r.reset()),this.blobs.clear(),this.injector?.dispose(),this.container.childNodes.forEach(r=>{(r.nodeType===Node.ELEMENT_NODE||r.nodeType===Node.TEXT_NODE)&&r.remove()})}async update(e,i,s,c=!1){for(;this.forcedUpdate;)await this.forcedUpdate;const h=++this.updateSequence;let r=this.positions.findIndex(o=>o.locations.position===i.locations.position);if(r<0)throw Error(`Locator not found in position list: ${i.locations.position} > ${this.positions.reduce((o,g)=>g.locations.position||0>o?g.locations.position||0:o,0)}`);const n=this.positions[r].href;this.inprogress.has(n)&&await this.inprogress.get(n);const p=new Promise(async(o,g)=>{const m=[],d=[];this.positions.forEach((t,a)=>{(a>r+w||a<r-w)&&(m.includes(t.href)||m.push(t.href)),a<r+y&&a>r-y&&(d.includes(t.href)||d.push(t.href))}),m.forEach(async t=>{d.includes(t)||this.pool.has(t)&&(await this.pool.get(t)?.destroy(),this.pool.delete(t),this.pendingUpdates.has(t)&&this.pendingUpdates.set(t,{inPool:!1}))}),this.currentBaseURL!==void 0&&e.baseURL!==this.currentBaseURL&&(this.blobs.forEach(t=>t.reset()),this.blobs.clear()),this.currentBaseURL=e.baseURL,c&&(this.blobs.forEach(t=>t.reset()),this.blobs.clear(),this.pendingUpdates.clear());const b=async t=>{if(this.pendingUpdates.has(t)&&this.pendingUpdates.get(t)?.inPool===!1){const f=this.blobs.get(t);f&&(f.reset(),this.blobs.delete(t),this.pendingUpdates.delete(t))}if(this.pool.has(t)){const f=this.pool.get(t);if(!this.blobs.has(t))await f.destroy(),this.pool.delete(t),this.pendingUpdates.delete(t);else{await f.load(s);return}}const a=e.readingOrder.findWithHref(t);if(!a)return;this.blobs.has(t)||this.blobs.set(t,new P(e,this.currentBaseURL||"",a,{cssProperties:this.currentCssProperties,injector:this.injector,upgradeInsecureRequests:this.upgradeInsecureRequests}));const l=new U(await this.blobs.get(t).build(),this.contentProtectionConfig,this.keyboardPeripheralsConfig,this.getFragmentIds(t),this.resizeWatchSelectors);return t!==n&&await l.hide(),this.container.appendChild(l.iframe),await l.load(s),this.pool.set(t,l),l};try{await Promise.all(d.filter(t=>t===n).map(t=>b(t)))}catch(t){g(t);return}if(h!==this.updateSequence){o();return}Promise.all(d.filter(t=>t!==n&&!this.inprogress.has(t)).map(async t=>{const a=b(t);this.inprogress.set(t,a);try{await a}finally{this.inprogress.get(t)===a&&this.inprogress.delete(t)}})).catch(t=>console.warn("Failed preloading frame",t));const u=this.pool.get(n);if(!u){o();return}if(u?.source!==this._currentFrame?.source||c){if(await this._currentFrame?.hide(),h!==this.updateSequence){o();return}const t=this.pool.get(n);if(!t){o();return}if(await t.load(s),h!==this.updateSequence){o();return}const a=this.pool.get(n);if(!a){o();return}if(await a.show(i.locations.progression),this._currentFrame=a,u){const l=this.container.ownerDocument.activeElement;l&&l.tagName==="IFRAME"&&l!==u.iframe&&u.iframe.focus({preventScroll:!0})}}o()});if(this.inprogress.set(n,p),c){const o=p.catch(()=>{});this.forcedUpdate=o,o.then(()=>{this.forcedUpdate===o&&(this.forcedUpdate=void 0)})}try{await p}finally{this.inprogress.delete(n)}}setCSSProperties(e){if(!((s,c)=>{const h=Object.keys(s),r=Object.keys(c);if(h.length!==r.length)return!1;for(const n of h)if(s[n]!==c[n])return!1;return!0})(this.currentCssProperties||{},e)){this.currentCssProperties=e,this.pool.forEach(s=>{s.setCSSProperties(e)});for(const s of this.blobs.keys())this.pendingUpdates.set(s,{inPool:this.pool.has(s)})}}get currentFrames(){return[this._currentFrame]}_frameFor(e){return this.pool.get(e)}get currentBounds(){const e={x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0,toJSON(){return this}};return this.currentFrames.forEach(i=>{if(!i)return;const s=i.realSize;e.x=Math.min(e.x,s.x),e.y=Math.min(e.y,s.y),e.width+=s.width,e.height=Math.max(e.height,s.height),e.top=Math.min(e.top,s.top),e.right=Math.min(e.right,s.right),e.bottom=Math.min(e.bottom,s.bottom),e.left=Math.min(e.left,s.left)}),e}}export{F as FramePoolManager};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{MediaNavigator as o,Navigator as t,VisualNavigator as a}from"./Navigator.js";import{BUILTIN_DECORATION_TYPES as
|
|
1
|
+
import{MediaNavigator as o,Navigator as t,VisualNavigator as a}from"./Navigator.js";import{BUILTIN_DECORATION_TYPES as n,DecorationLayout as f,DecorationStyleType as p,DecorationWidth as g,decorationsEqual as m,resolveDecorationForWire as u,supportsDecorationStyle as s}from"@readium/decorator";import{ExperimentalWebPubNavigator as x,WebPubNavigator as d}from"./webpub/WebPubNavigator.js";import{WebPubBlobBuilder as c}from"./webpub/WebPubBlobBuilder.js";import{WebPubFrameManager as R}from"./webpub/WebPubFrameManager.js";import{WebPubFramePoolManager as S}from"./webpub/WebPubFramePoolManager.js";import{WebPubDefaults as E}from"./webpub/preferences/WebPubDefaults.js";import{WebPubPreferencesEditor as h}from"./webpub/preferences/WebPubPreferencesEditor.js";import{WebPubPreferences as y}from"./webpub/preferences/WebPubPreferences.js";import{WebPubSettings as L}from"./webpub/preferences/WebPubSettings.js";import{WebRSProperties as M,WebUserProperties as N}from"./webpub/css/Properties.js";import{WebPubCSS as T}from"./webpub/css/WebPubCSS.js";import{EpubNavigator as I}from"./epub/EpubNavigator.js";import{FrameComms as X}from"./epub/frame/FrameComms.js";import{FrameManager as H}from"./epub/frame/FrameManager.js";import{FramePoolManager as z}from"./epub/frame/FramePoolManager.js";import{FXLCoordinator as q,HorizontalThird as w,VerticalThird as G}from"./epub/fxl/FXLCoordinator.js";import{FXLFrameManager as j}from"./epub/fxl/FXLFrameManager.js";import{FXLFramePoolManager as J}from"./epub/fxl/FXLFramePoolManager.js";import{FXLPeripherals as Z,isTypedOMSupported as $}from"./epub/fxl/FXLPeripherals.js";import{FXLSpreader as re,Orientation as oe,Spread as te}from"./epub/fxl/FXLSpreader.js";import{EpubDefaults as ie}from"./epub/preferences/EpubDefaults.js";import{EpubPreferencesEditor as fe}from"./epub/preferences/EpubPreferencesEditor.js";import{EpubPreferences as ge}from"./epub/preferences/EpubPreferences.js";import{EpubSettings as ue}from"./epub/preferences/EpubSettings.js";import{RSProperties as le,UserProperties as xe}from"./epub/css/Properties.js";import{ReadiumCSS as Pe}from"./epub/css/ReadiumCSS.js";import{DivinaNavigator as be}from"./divina/DivinaNavigator.js";import{DivinaPage as ve,DivinaSpreader as Se}from"./divina/DivinaSpreader.js";import{DivinaPageManager as Ee,placeholderSVG as Ce}from"./divina/DivinaPageManager.js";import{DivinaPagedPresenter as We}from"./divina/DivinaPagedPresenter.js";import{DivinaScrolledPresenter as Ae}from"./divina/DivinaScrolledPresenter.js";import{DivinaPeripherals as Fe}from"./divina/DivinaPeripherals.js";import{DivinaQuality as Ne,MOBILE_MAX_HEIGHT as Ve,MOBILE_MAX_WIDTH as Te,gatherVariants as Be,selectVariant as Ie}from"./divina/DivinaVariantSelector.js";import{DivinaDefaults as Xe}from"./divina/preferences/DivinaDefaults.js";import{DivinaPreferences as He,stripWidthRangeConfig as ke}from"./divina/preferences/DivinaPreferences.js";import{DivinaPreferencesEditor as Qe}from"./divina/preferences/DivinaPreferencesEditor.js";import{DivinaSettings as we}from"./divina/preferences/DivinaSettings.js";import{WebAudioEngine as Ue}from"./audio/engine/WebAudioEngine.js";import{AudioPreferences as Ye}from"./audio/preferences/AudioPreferences.js";import{AudioDefaults as Ke}from"./audio/preferences/AudioDefaults.js";import{AudioSettings as $e}from"./audio/preferences/AudioSettings.js";import{AudioPreferencesEditor as rr}from"./audio/preferences/AudioPreferencesEditor.js";import{AudioNavigator as tr}from"./audio/AudioNavigator.js";import{LineLengths as ir}from"./helpers/lineLength.js";import{getScriptMode as fr}from"./helpers/scriptMode.js";import{BooleanPreference as gr,EnumPreference as mr,Preference as ur,RangePreference as sr}from"./preferences/Preference.js";import{TextAlignment as xr,experiments as dr,filterRangeConfig as Pr,fontSizeRangeConfig as cr,fontWeightRangeConfig as br,fontWidthRangeConfig as Rr,i18n as vr,letterSpacingRangeConfig as Sr,lineHeightRangeConfig as Dr,lineLengthRangeConfig as Er,paragraphIndentRangeConfig as Cr,paragraphSpacingRangeConfig as hr,playbackRateRangeConfig as Wr,settings as yr,skipIntervalRangeConfig as Ar,volumeRangeConfig as Lr,wordSpacingRangeConfig as Fr,zoomRangeConfig as Mr}from"./preferences/Types.js";import{ensureBoolean as Vr,ensureDecorationStyle as Tr,ensureEnumValue as Br,ensureExperiment as Ir,ensureFilter as Or,ensureLessThanOrEqual as Xr,ensureMoreThanOrEqual as _r,ensureNonNegative as Hr,ensureString as kr,ensureValueInRange as zr,withFallback as Qr}from"./preferences/guards.js";import{Properties as wr}from"./css/Properties.js";import{Injector as Ur}from"./injection/Injector.js";import{defaultContextualizations as Yr,filterByLanguages as Jr,filterOutNoveltyVoices as Kr,filterOutVeryLowQualityVoices as Zr,getQualityValue as $r,groupVoicesByLanguage as eo,skippableRoles as ro,sortAlphabetically as oo,sortByQuality as to,sortVoicesByRegions as ao}from"@readium/speech";import{PublicationGuidedNavigationProvider as no}from"./readaloud/GuidedNavigationProvider.js";import{ReadAloudNavigator as po}from"./readaloud/ReadAloudNavigator.js";import{ReadAloudDefaults as mo}from"./readaloud/preferences/ReadAloudDefaults.js";import{ReadAloudAutoPause as so,ReadAloudPreferences as lo}from"./readaloud/preferences/ReadAloudPreferences.js";import{ReadAloudPreferencesEditor as Po}from"./readaloud/preferences/ReadAloudPreferencesEditor.js";import{ReadAloudSettings as bo}from"./readaloud/preferences/ReadAloudSettings.js";export{Ke as AudioDefaults,tr as AudioNavigator,Ye as AudioPreferences,rr as AudioPreferencesEditor,$e as AudioSettings,n as BUILTIN_DECORATION_TYPES,gr as BooleanPreference,f as DecorationLayout,p as DecorationStyleType,g as DecorationWidth,Xe as DivinaDefaults,be as DivinaNavigator,ve as DivinaPage,Ee as DivinaPageManager,We as DivinaPagedPresenter,Fe as DivinaPeripherals,He as DivinaPreferences,Qe as DivinaPreferencesEditor,Ne as DivinaQuality,Ae as DivinaScrolledPresenter,we as DivinaSettings,Se as DivinaSpreader,mr as EnumPreference,ie as EpubDefaults,I as EpubNavigator,ge as EpubPreferences,fe as EpubPreferencesEditor,ue as EpubSettings,x as ExperimentalWebPubNavigator,q as FXLCoordinator,j as FXLFrameManager,J as FXLFramePoolManager,Z as FXLPeripherals,re as FXLSpreader,X as FrameComms,H as FrameManager,z as FramePoolManager,w as HorizontalThird,Ur as Injector,ir as LineLengths,Ve as MOBILE_MAX_HEIGHT,Te as MOBILE_MAX_WIDTH,o as MediaNavigator,t as Navigator,oe as Orientation,ur as Preference,wr as Properties,no as PublicationGuidedNavigationProvider,le as RSProperties,sr as RangePreference,so as ReadAloudAutoPause,mo as ReadAloudDefaults,po as ReadAloudNavigator,lo as ReadAloudPreferences,Po as ReadAloudPreferencesEditor,bo as ReadAloudSettings,Pe as ReadiumCSS,te as Spread,xr as TextAlignment,xe as UserProperties,G as VerticalThird,a as VisualNavigator,Ue as WebAudioEngine,c as WebPubBlobBuilder,T as WebPubCSS,E as WebPubDefaults,R as WebPubFrameManager,S as WebPubFramePoolManager,d as WebPubNavigator,y as WebPubPreferences,h as WebPubPreferencesEditor,L as WebPubSettings,M as WebRSProperties,N as WebUserProperties,m as decorationsEqual,Yr as defaultContextualizations,Vr as ensureBoolean,Tr as ensureDecorationStyle,Br as ensureEnumValue,Ir as ensureExperiment,Or as ensureFilter,Xr as ensureLessThanOrEqual,_r as ensureMoreThanOrEqual,Hr as ensureNonNegative,kr as ensureString,zr as ensureValueInRange,dr as experiments,Jr as filterByLanguages,Kr as filterOutNoveltyVoices,Zr as filterOutVeryLowQualityVoices,Pr as filterRangeConfig,cr as fontSizeRangeConfig,br as fontWeightRangeConfig,Rr as fontWidthRangeConfig,Be as gatherVariants,$r as getQualityValue,fr as getScriptMode,eo as groupVoicesByLanguage,vr as i18n,$ as isTypedOMSupported,Sr as letterSpacingRangeConfig,Dr as lineHeightRangeConfig,Er as lineLengthRangeConfig,Cr as paragraphIndentRangeConfig,hr as paragraphSpacingRangeConfig,Ce as placeholderSVG,Wr as playbackRateRangeConfig,u as resolveDecorationForWire,Ie as selectVariant,yr as settings,Ar as skipIntervalRangeConfig,ro as skippableRoles,oo as sortAlphabetically,to as sortByQuality,ao as sortVoicesByRegions,ke as stripWidthRangeConfig,s as supportsDecorationStyle,Lr as volumeRangeConfig,Qr as withFallback,Fr as wordSpacingRangeConfig,Mr as zoomRangeConfig};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{experiments as o}from"./Types.js";function
|
|
1
|
+
import{experiments as o}from"./Types.js";function u(n,r){return n==null||r==null||n<=r?n:void 0}function f(n,r){return n==null||r==null||n>=r?n:void 0}function d(n){return typeof n=="string"?n:n===null?null:void 0}function s(n){return typeof n=="boolean"||n==null?n:void 0}function l(n,r){if(n!==void 0)return n===null?null:r[n]!==void 0?n:void 0}function c(n){return typeof n=="boolean"||typeof n=="number"&&n>=0?n:n===null?null:void 0}function y(n){if(n!==void 0)return n===null?null:n<0?void 0:n}function b(n,r){if(n===void 0)return;if(n===null)return null;const i=Math.min(...r),t=Math.max(...r);return n>=i&&n<=t?n:void 0}function h(n){if(n==null||n===!1)return n;if(typeof n!="object")return;const r=n.type;return r===void 0||typeof r=="string"?n:void 0}function g(n,r){return n===void 0?r:n}function m(n){if(n!==void 0)return n===null?null:n.filter(r=>r in o)}export{s as ensureBoolean,h as ensureDecorationStyle,l as ensureEnumValue,m as ensureExperiment,c as ensureFilter,u as ensureLessThanOrEqual,f as ensureMoreThanOrEqual,y as ensureNonNegative,d as ensureString,b as ensureValueInRange,g as withFallback};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{GuidedNavigationObject as a}from"@readium/shared";import{makeGnd as d,decodeTextref as u}from"@readium/guided-navigation";class h{constructor(r,e={}){this.publication=r,this.options=e}async guideFor(r){const e=r.href.split("#")[0];if(!this.options.generateFromMarkup){const i=await this.publication.guideForLink(r,{skipAudio:!0}).catch(()=>{});if(i){const t=this.objectsIn(i.guided,e);if(t.length>0&&this.isLocatable(t))return t}}return this.generate(r,e)}async generate(r,e){const i=this.publication.get(r);try{const t=await i.link();if(!t.mediaType.isHTML)return;const n=await i.readAsXML();if(!n||n.getElementsByTagNameNS("*","parsererror").length>0)return;const s=n.querySelector("body");if(!s)return;const o=t.mediaType.essence==="text/html"?"text/html":"application/xhtml+xml";return d(s,o,{textrefs:{roles:!0},href:e})?.guided}finally{i.close()}}objectsIn(r,e,i){return r.flatMap(t=>{const n=this.resourceOf(t)??i,s=t.children?this.objectsIn(t.children,e,n):[];if(n!==void 0&&n!==e)return s;if(s.length===0&&!t.text&&!t.textref&&!t.imgref)return[];const o=t.textref?.startsWith("#")?e+t.textref:t.textref;return[new a({...t,textref:o,children:s.length>0?s:void 0})]})}resourceOf(r){const e=r.textref?.split("#")[0];return e||this.imageOf(r)}imageOf(r){const e=r.imgref?.split("#")[0];return e&&this.publication.readingOrder.findWithHref(e)?e:void 0}isLocatable(r,e=!1){return r.every(i=>{const t=i.textref?u(i)!==void 0:this.imageOf(i)!==void 0,n=e||t;return i.text&&!n?!1:!i.children||this.isLocatable(i.children,n)})}}export{h as PublicationGuidedNavigationProvider};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getCssSelector as w,Layout as u,Locator as k,Profile as L}from"@readium/shared";import{ReadiumSpeechNavigator as x,filterByLanguages as b,sortVoicesByRegions as B,resolveUtteranceLocate as C,createLocator as T,SpeechPreferences as S,WebSpeechEngine as O,WebSpeechVoiceManager as U}from"@readium/speech";import{PublicationGuidedNavigationProvider as _}from"./GuidedNavigationProvider.js";import{GuidedNavigationPool as R,ReadingUnits as H}from"./ReadingUnit.js";import{SpeechProgress as A}from"./SpeechProgress.js";import{ReadAloudPreferences as E,ReadAloudAutoPause as l}from"./preferences/ReadAloudPreferences.js";import{ReadAloudDefaults as I}from"./preferences/ReadAloudDefaults.js";import{ReadAloudSettings as v}from"./preferences/ReadAloudSettings.js";import{ReadAloudPreferencesEditor as y}from"./preferences/ReadAloudPreferencesEditor.js";class V extends O{constructor(t){super(),this.languages=t}async initialize(){const t=this.languages?.length?this.languages:void 0;if(!await super.initialize({languages:t}))return!1;if(this.getCurrentVoice())return!0;const e=(await this.getAvailableVoices()).filter(n=>n.controls?.boundary!==!1),i=await(await U.initialize({languages:t})).getDefaultVoice(t??[...navigator.languages??["en"]],e);return i&&await this.setVoice(i),!0}}const F="readaloud-utterance",M="readaloud-word",m=1e3,g=1;class f{constructor(t,e={},s={}){this.navigator=t,this.listeners=e,this.unsubscribers=[],this._preferencesEditor=null,this.utteranceLocators=[],this.detached=!1,this.navigationLocked=!1,this.watchedPieces=new Map,this.lines=[],this.progress=new A,this.loading=!1,this.loadPaused=!1,this.loadToken=0,this.lastState="idle",this.detachable=s.detachable??!0,this.pool=new R(t.publication,s.provider??new _(t.publication)),this.units=new H(t),this._preferences=new E(s.preferences),this._defaults=new I(s.defaults),this.speech=new x(s.engine??new V(t.publication.metadata.languages),{preferences:f.speechPreferences(this._preferences),defaults:f.speechPreferences({...this._defaults.speech,autoPause:this._defaults.autoPause})}),this._settings=new v(this.speech.settings,this._preferences,this._defaults),this.speech.setSpeakInContentLanguage(this._settings.speakInContentLanguage),this.listen()}get state(){return this.loading?"loading":this.turning?"playing":this.pausedBefore?"paused":this.speech.getState()}async play(t){if(!t&&this.loading){this.loadPaused=!1;return}if(!t&&this.turning)return;if(!t&&this.pausedBefore){await this.resumePaused(this.pausedBefore);return}const e=this.state;if(!t&&(e==="paused"||e==="ready")){this.speech.play();return}!t&&e==="playing"||(this.attach(),await this.start(t??this.navigator.currentLocator))}async readFromPointer(t){if(t.interactiveElement||!t.onContent||!this.navigator.findPointedPiece)return!1;const e=this.unit,s=e?await this.pointedIndex(t,this.speech.getContentQueue()):-1;if(e&&s>=0)return this.attach(),this.loadUnit(()=>e,()=>s);const i=this.navigator.currentLocator.href.split("#")[0];return e?.links.some(n=>n.href.split("#")[0]===i)?!1:(this.attach(),this.loadUnit(()=>this.units.around(i),async n=>{const r=await this.pointedIndex(t,n);return r>=0?r:this.startIndex(n,this.navigator.currentLocator)}))}pause(){this.loading?this.loadPaused=!0:this.turning?this.pauseTurning():this.pausedBefore||this.speech.pause()}stop(){this.loadToken++,this.settleReady?.(),this.attach(),this.pausedBefore=void 0,this.turning=void 0,this.setLoading(!1),this.speech.stop()}async next(){return this.attach(),this.turning&&this.pauseTurning(),this.pausedBefore?this.movePaused(this.pausedBefore,1):this.speech.next()?!0:!this.unit||!this.units.linkAfter(this.unit)?!1:this.loadUnit(()=>this.units.after(this.unit),()=>0,this.staysPaused())}async previous(){return this.attach(),this.turning&&this.pauseTurning(),this.pausedBefore?this.movePaused(this.pausedBefore,-1):this.speech.previous()?!0:!this.unit||!this.units.linkBefore(this.unit)?!1:this.loadUnit(()=>this.units.before(this.unit),t=>t.length-1,this.staysPaused())}async getVoices(t={}){const e=await this.speech.getVoices(),s=t.languages?.length?t.languages:void 0,i=s?b(e,s):e,n=this.navigator.publication.metadata.languages,r=s??(n?.length?n:[...navigator.languages??["en"]]);return B(r,i)}setVoice(t){this.speech.setVoice(t)}getCurrentVoice(){return this.speech.getCurrentVoice()}get settings(){return Object.freeze({...this._settings})}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new y(this._preferences,this.settings,this.speech.settings,this.layout())),this._preferencesEditor}async submitPreferences(t){this._preferences=this._preferences.merging(t);const e=this.speech.getContentQueue();await this.speech.submitPreferences(f.speechPreferences(this._preferences)),this._settings=new v(this.speech.settings,this._preferences,this._defaults),this.speech.setSpeakInContentLanguage(this._settings.speakInContentLanguage);const s=this.pausedBefore??this.turning;s&&(s.index=this.indexAfterRebuild(e,s.index),this.pausedBefore?.current&&this.notifyUtterance(this.speech.getContentQueue()[s.index])),this.unit&&this.watchLayout(this.speech.getContentQueue()),this._preferencesEditor!==null&&(this._preferencesEditor=new y(this._preferences,this.settings,this.speech.settings,this.layout())),this.decorate()}async destroy(){this.loadToken++,this.settleReady?.(),this.pausedBefore=void 0,this.turning=void 0,this.unsubscribers.forEach(t=>t()),this.unsubscribers.length=0,this.clearBreak(),clearTimeout(this.following),this.following=void 0,this.unwatchLayout?.(),this.unwatchLayout=void 0,this.clearHighlights(),this.lockNavigation(!1),await this.speech.destroy()}listen(){const t=(e,s)=>{this.unsubscribers.push(this.speech.on(e,i=>{s(i),this.notifyState()}))};t("start",()=>{const e=this.speech.getCurrentContent();e&&this.progress.start(e),this.notifyUtterance(),this.armBreak()}),t("skip",()=>{this.clearBreak(),this.progress.reset(),this.notifyUtterance()}),t("boundary",e=>{if(!this.sendsBoundaries()||e.detail?.name!=="word"||!e.detail.locate||!e.detail.word?.trim())return;const s=e.detail.locate,i=this.locatorFor(s);if(!i)return;this.wordLocator=i,this.decorate();const n=this.wordPoint(s);n&&this.isHidden(n)&&this.follow(i),this.listeners.wordChanged?.(i,e.detail.word??"")}),t("pause",()=>{this.clearBreak(),this.progress.pause()}),t("resume",()=>{this.progress.resume(),this.armBreak()}),t("end",()=>{this.clearBreak(),this.progress.end(this.speech.getCurrentContent(),this.voiceName(),this.speech.settings.rate);const e=this.speech.getState();if(e==="idle"){const n=this.unit,r=this.units.linkAfter(n);r?this.loadUnit(()=>this.units.after(n),()=>0,this.pausesBeforeUnit(r.href)):this.clearHighlights();return}if(e!=="playing")return;const s=this.speech.getContentQueue(),i=s.indexOf(this.speech.getCurrentContent());i<0||i+1>=s.length||(this.pausesBetween(s[i],s[i+1])?(this.pausedBefore={unit:this.unit,index:i+1,current:!0},this.speech.stop(),this.notifyUtterance(s[i+1])):this.layout()===u.reflowable&&this.pausesAtPages()&&this.turnTo(i+1))}),t("error",e=>{this.clearBreak(),this.progress.reset(),this.clearHighlights(),this.listeners.error?.(e.detail??e)}),t("stop",()=>{this.clearBreak(),this.progress.reset(),!this.pausedBefore&&!this.turning&&this.clearHighlights()});for(const e of["idle","loading","ready"])t(e,()=>{})}async start(t){await this.loadUnit(()=>this.units.around(t.href.split("#")[0]),e=>this.startIndex(e,t))}async resumePaused(t){if(t.unit!==this.unit){await this.loadUnit(()=>t.unit,()=>t.index);return}if(this.speech.getState()==="loading"&&!await this.speechReady())return;const e=this.pausedBefore??t;this.pausedBefore=void 0,this.speakFrom(e.index),this.notifyState()}async speechReady(){const t=++this.loadToken;return this.loadPaused=!1,this.setLoading(!0),await this.untilReady(),t!==this.loadToken?!1:(this.setLoading(!1),!this.loadPaused)}untilReady(){return this.settleReady?.(),new Promise(t=>{const e=()=>{s(),this.settleReady===e&&(this.settleReady=void 0),t()},s=this.speech.on("ready",e);this.settleReady=e})}async movePaused(t,e){const s=(t.current?t.index:t.index-1)+e;if(t.unit===this.unit){const i=this.speech.getContentQueue();if(s>=0&&s<i.length)return this.pausedBefore={unit:t.unit,index:s,current:!0},this.notifyUtterance(i[s]),!0;if(s>=i.length)return this.units.linkAfter(t.unit)?this.loadUnit(()=>this.units.after(t.unit),()=>s-i.length,!0):!1}return s>=0?this.loadUnit(()=>t.unit,()=>s,!0):this.units.linkBefore(t.unit)?this.loadUnit(()=>this.units.before(t.unit),i=>i.length+s,!0):!1}async loadUnit(t,e,s=!1){const i=++this.loadToken;this.loadPaused=s,this.setLoading(!0),this.pausedBefore=void 0,this.turning=void 0,this.speech.stop();try{const n=t();if(!n)return this.setLoading(!1),!1;const{guided:r,failures:o}=await this.pool.stitch(n);if(i!==this.loadToken)return!1;o.forEach(P=>this.listeners.error?.(P.error));const a=this.untilReady();if(await this.speech.loadGndContent(r),i!==this.loadToken)return!1;this.unit=n;const c=this.speech.getContentQueue();if(c.length===0)return this.setLoading(!1),this.units.linkAfter(n)?this.loadUnit(()=>this.units.after(n),()=>0,this.loadPaused):!1;if(await a,i!==this.loadToken)return!1;const h=await e(c);if(i!==this.loadToken)return!1;this.setLoading(!1);const d=this.speech.getContentQueue();this.watchLayout(d);const p=Math.max(Math.min(this.indexAfterRebuild(c,Math.max(h,0)),d.length-1),0);return this.loadPaused?(this.pausedBefore={unit:n,index:p,current:!0},this.notifyUtterance(d[p]),this.notifyState()):this.speakFrom(p),!0}catch(n){return i===this.loadToken&&this.setLoading(!1),this.listeners.error?.(n),!1}}startIndex(t,e){const s=e.href.split("#")[0],i=e.locations?w(e.locations):void 0,n=e.text?.highlight?.trim().slice(0,40);let r=-1,o=-1;for(let a=0;a<t.length;a++){const c=this.piecesOf(t[a]).filter(h=>h.href?.split("#")[0]===s);if(c.length!==0){if(r===-1&&(r=a),i&&c.some(h=>h.cssSelector===i))return a;o===-1&&n&&(t[a].plain??"").includes(n)&&(o=a)}}return o!==-1?o:Math.max(r,0)}indexAfterRebuild(t,e){const s=this.speech.getContentQueue();if(s.length===t.length&&s.every((r,o)=>r===t[o]))return e;const i=t[e]&&this.piecesOf(t[e])[0],n=i&&this.locatorFor(i);return n?this.startIndex(s,n):0}async pointedIndex(t,e){const s=e.flatMap((n,r)=>this.piecesOf(n).map(o=>({index:r,locator:this.locatorFor(o)}))).filter(n=>n.locator!==void 0),i=await this.navigator.findPointedPiece?.(t,s.map(n=>n.locator));return s.find(n=>n.locator===i)?.index??-1}piecesOf(t){return C(t,this.speech.settings.segmentation)}speakFrom(t){t===0?this.speech.play():this.speech.jumpTo(t,!0)}pausesAtPages(){const t=this._settings.autoPause;switch(this.layout()){case u.fixed:return t===l.page||t===l.spread;case u.reflowable:return t===l.page;default:return!1}}turnTo(t){const e=this.speech.getContentQueue()[t],s=this.piecesOf(e).map(h=>this.locatorFor(h)).find(h=>h!==void 0);if(!s||document.hidden||this.isDetached())return;const i={unit:this.unit,index:t};this.turning=i,this.speech.stop();const n=this.navigator.viewport?.progressions.get(s.href),r=n?.start,o=n?.end,a=h=>{clearTimeout(c),this.turning===i&&(this.turning=void 0,h?(this.pausedBefore={...i,current:!0},this.notifyUtterance(this.speech.getContentQueue()[i.index])):(this.pausedBefore={...i,current:!0},this.resumePaused(this.pausedBefore)),this.notifyState())},c=setTimeout(()=>a(!1),m);this.followedHref=s.href,this.navigator.go(s,!1,h=>{const d=this.navigator.viewport?.progressions.get(s.href);a(h&&d!==void 0&&(d.start!==r||d.end!==o))})}staysPaused(){return this.loading?this.loadPaused:this.speech.getState()==="paused"}pauseTurning(){this.pausedBefore={...this.turning,current:!1},this.turning=void 0,this.notifyState()}pausesBeforeUnit(t){if(!this.pausesAtPages())return!1;const e=this.navigator.viewport?.readingOrder??[];return this._settings.autoPause!==l.spread||e.length===0?!0:!e.includes(t)}pausesBetween(t,e){if(!e||!this.pausesAtPages())return!1;const s=this.hrefsOf(e)[0];if(!s)return!1;const i=this.navigator.viewport?.readingOrder??[];return this._settings.autoPause===l.spread&&i.length>0?!i.includes(s):s!==this.hrefsOf(t).at(-1)}hrefsOf(t){return this.piecesOf(t).map(e=>e.href&&this.navigator.publication.readingOrder.findWithHref(e.href.split("#")[0])?.href).filter(e=>!!e)}notifyUtterance(t=this.speech.getCurrentContent()){if(!t)return;const e=this.piecesOf(t).map(s=>this.locatorFor(s)).filter(s=>s!==void 0);if(this.utteranceLocators=e,this.wordLocator=void 0,this.decorate(),e.length>0){const s=this.utteranceStart(t);(!s||this.isHidden(s)!==!1)&&this.follow(e[0])}else{const s=this.pageLocator();s&&(e.push(s),s.href!==this.followedHref&&this.follow(s))}this.listeners.utteranceChanged?.({text:t.plain??"",locators:e})}pageLocator(){const t=this.unit?.links;return t?.length===1&&t[0].mediaType.isBitmap?t[0].locator:void 0}decorate(){this.applyDecorations(F,this.utteranceLocators,this._settings.utteranceStyle),this.applyDecorations(M,this.wordLocator?[this.wordLocator]:[],this._settings.wordStyle)}applyDecorations(t,e,s){const i=s?e.map((n,r)=>({id:`${t}-${r}`,locator:n,style:s})):[];this.navigator.applyDecorations?.(i,t)}clearHighlights(){this.utteranceLocators=[],this.wordLocator=void 0,this.decorate(),this.followedHref=void 0}follow(t){if(this.units.displays(t.href)||this.following!==void 0||this.isDetached())return;this.followedHref=t.href;const e=()=>{this.following===s&&(clearTimeout(s),this.following=void 0)},s=setTimeout(e,m);this.following=s,this.navigator.go(t,!1,i=>{i&&this.following===s&&(this.shownHref=t.href.split("#")[0]),e()})}attach(){this.detached=!1,this.shownHref=void 0}isDetached(){const t=this.navigator.currentLocator.href.split("#")[0];return this.detachable&&this.shownHref&&this.shownHref!==t&&this.layout()!==u.fixed&&(this.detached=!0),this.detached}watchLayout(t){if(this.unwatchLayout?.(),this.unwatchLayout=void 0,this.watchedPieces.clear(),this.lines=[],this.viewport=void 0,!this.navigator.watchTextLayout||this.layout()===u.fixed)return;const e=[];for(const s of t.flatMap(i=>this.piecesOf(i))){const i=this.locatorFor(s);!i||this.watchedPieces.has(s)||(this.watchedPieces.set(s,e.length),e.push(i))}e.length!==0&&(this.unwatchLayout=this.navigator.watchTextLayout(e,s=>this.laidOut(s)))}laidOut(t){this.shownHref=this.navigator.currentLocator.href.split("#")[0],this.viewport=t.viewport,t.pieces&&(this.lines=t.pieces);const e=this.spokenPoint(),s=e&&this.isHidden(e);if(s===!1)this.detached=!1;else if(s&&t.pieces){const i=this.pointLocator(e);i&&this.follow(i)}else s&&this.detachable&&this.following===void 0&&!this.turning&&(this.detached=!0);(this.breakTimer!==void 0||this.progress.speaking)&&this.armBreak()}isHidden(t){const e=this.lineStart(t);if(e===void 0||!this.viewport)return;const{pos:s,size:i}=this.viewport;return e<s-g||e>=s+i-g}lineStart(t){const e=this.lines[t.piece];if(!e||e.offsets.length===0)return;let s=0;for(;s+1<e.offsets.length&&e.offsets[s+1]<=t.offset;)s++;return e.starts[s]}spokenPoint(){const t=this.speech.getCurrentContent();if(t){if(this.wordLocator?.text&&this.sendsBoundaries()){const e=this.wordPoint({cssSelector:w(this.wordLocator.locations),text:this.wordLocator.text});if(e)return e}if(!this.sendsBoundaries()&&this.progress.speaking){const e=this.pointAt(t,this.progress.elapsed()*this.speed());if(e)return e}return this.utteranceStart(t)}}utteranceStart(t){const e=this.watchedPieces.get(this.piecesOf(t)[0]);return e===void 0?void 0:{piece:e,offset:0}}wordPoint(t){const e=this.speech.getCurrentContent(),s=t.text;if(!e||!s)return;const i=(s.before??"")+(s.highlight??"")+(s.after??""),n=this.piecesOf(e).find(o=>o.cssSelector===t.cssSelector&&o.text?.highlight===i),r=n&&this.watchedPieces.get(n);return r===void 0?void 0:{piece:r,offset:f.collapsed(s.before??"").length}}pointAt(t,e){let s=e;for(const i of this.piecesOf(t)){const n=this.watchedPieces.get(i),r=f.collapsed(i.text?.highlight??"").length;if(n!==void 0&&s<r)return{piece:n,offset:Math.max(0,Math.floor(s))};s-=r}}pointLocator(t){const e=[...this.watchedPieces].find(([,n])=>n===t.piece)?.[0],s=e?.text?.highlight;if(!e||!s)return;const i=f.rawOffset(s,t.offset);return this.locatorFor({...e,domRange:void 0,text:{before:s.slice(0,i),highlight:s.slice(i,i+1),after:s.slice(i+1)}})}armBreak(){this.clearBreak();const t=this.speech.getCurrentContent();if(!t||this.detached||this.sendsBoundaries()||!this.progress.speaking||!this.viewport)return;const e=this.viewport.pos+this.viewport.size-g;let s=0;for(const i of this.piecesOf(t)){const n=this.watchedPieces.get(i),r=n===void 0?null:this.lines[n],o=r?.starts.findIndex(a=>a>=e)??-1;if(n!==void 0&&r&&o>=0){const a={piece:n,offset:r.offsets[o]},c=(s+a.offset)/this.speed()-this.progress.elapsed();this.breakTimer=setTimeout(()=>{this.breakTimer=void 0;const h=this.pointLocator(a);h&&this.follow(h)},Math.max(0,c*1e3));return}s+=f.collapsed(i.text?.highlight??"").length}}clearBreak(){clearTimeout(this.breakTimer),this.breakTimer=void 0}sendsBoundaries(){return this.speech.getCurrentVoice()?.controls?.boundary!==!1}voiceName(){return this.speech.getCurrentVoice()?.name??""}speed(){return this.progress.speed(this.voiceName(),this.speech.settings.rate)}static collapsed(t){return t.replace(/\s+/g," ")}static rawOffset(t,e){let s=0;for(let i=0;i<t.length;i++)if(!(/\s/.test(t[i])&&i>0&&/\s/.test(t[i-1]))){if(s===e)return i;s++}return t.length}locatorFor(t){if(!t.href)return;const e=this.navigator.publication.readingOrder.findWithHref(t.href.split("#")[0]);if(!e)return;const{text:s,locations:i}=T(t,{location:{href:e.href}});return new k({href:e.href,type:e.type??"text/html",text:s,locations:i})}layout(){const t=this.navigator.publication.metadata;return t.conformsTo?.includes(L.DIVINA)||t.effectiveLayout===u.fixed?u.fixed:this.navigator.layout===u.reflowable?u.reflowable:u.scrolled}static speechPreferences(t){const{autoPause:e,speakInContentLanguage:s,utteranceStyle:i,wordStyle:n,...r}=t,o=e===l.page||e===l.spread;return new S({...r,autoPause:o?l.none:e})}setLoading(t){this.loading=t,this.notifyState()}lockNavigation(t){t!==this.navigationLocked&&(this.navigationLocked=t,this.navigator.lockNavigation?.(t))}notifyState(){const t=this.state;this.lockNavigation(!this.detachable&&(t==="playing"||t==="loading")),t!==this.lastState&&(this.lastState=t,this.listeners.stateChanged?.(t))}}export{f as ReadAloudNavigator};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Layout as g,Profile as u}from"@readium/shared";class v{constructor(i){this.navigator=i;const t=i.publication.metadata;this.spreads=t.effectiveLayout===g.fixed&&!t.conformsTo?.includes(u.DIVINA)}around(i){const t=this.navigator.publication.readingOrder.findWithHref(i);if(t)return this.spreads&&!this.displays(t.href)&&this.navigator.go(t.locator,!1,()=>{}),this.displayedFrom(t,()=>!0)}linkAfter(i){const t=this.indexOf(i.links[i.links.length-1]);return t<0?void 0:this.navigator.publication.readingOrder.items[t+1]}linkBefore(i){const t=this.indexOf(i.links[0]);return t<=0?void 0:this.navigator.publication.readingOrder.items[t-1]}after(i){const t=this.linkAfter(i);if(!t)return;const e=i.links[i.links.length-1];return this.spreads&&this.move(e,t,s=>this.navigator.goForward(!1,s)),this.displayedFrom(t,s=>this.indexOf(s)>this.indexOf(e))}before(i){const t=this.linkBefore(i);if(!t)return;const e=i.links[0];return this.spreads&&this.move(e,t,s=>this.navigator.goBackward(!1,s)),this.displayedFrom(t,s=>this.indexOf(s)<this.indexOf(e))}displays(i){return this.spreads&&(this.navigator.viewport?.readingOrder??[]).includes(i)}move(i,t,e){this.displays(i.href)?e(()=>{}):this.navigator.go(t.locator,!1,()=>{})}displayedFrom(i,t){if(!this.spreads)return{links:[i]};const e=(this.navigator.viewport?.readingOrder??[]).map(s=>this.navigator.publication.readingOrder.findWithHref(s)).filter(s=>s!==void 0&&t(s)).sort((s,r)=>this.indexOf(s)-this.indexOf(r));return e.some(s=>s.href===i.href)?{links:e}:{links:[i]}}indexOf(i){return this.navigator.publication.readingOrder.findIndexWithHref(i.href)}}const d=10,h=5;class m{constructor(i,t){this.publication=i,this.provider=t,this.guides=new Map}async stitch(i,t=6){const e=new Array(i.links.length),s=[];let r=0;const o=async()=>{for(;r<i.links.length;){const n=r++,a=i.links[n];try{e[n]=await this.guideFor(a)}catch(c){s.push({index:n,link:a,error:c})}}},f=Promise.all(Array.from({length:Math.min(t,i.links.length)},o));return this.update(i),await f,{guided:e.flatMap(n=>n??[]),failures:s.sort((n,a)=>n.index-a.index).map(({link:n,error:a})=>({link:n,error:a}))}}update(i){const t=this.publication.readingOrder.items,e=this.publication.readingOrder.findIndexWithHref(i.links[0].href);e<0||t.forEach((s,r)=>{const o=s.href.split("#")[0];r>e+d||r<e-d?this.guides.delete(o):r<e+h&&r>e-h&&this.guideFor(s).catch(()=>{})})}guideFor(i){const t=i.href.split("#")[0];let e=this.guides.get(t);return e||(e=this.provider.guideFor(i),this.guides.set(t,e),e.catch(()=>{this.guides.get(t)===e&&this.guides.delete(t)})),e}}export{m as GuidedNavigationPool,v as ReadingUnits};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class a{constructor(){this.speeds=new Map,this.startedAt=0}start(t){this.utterance=t,this.startedAt=performance.now(),this.pausedAt=void 0}pause(){this.utterance&&this.pausedAt===void 0&&(this.pausedAt=performance.now())}resume(){this.pausedAt!==void 0&&(this.startedAt+=performance.now()-this.pausedAt,this.pausedAt=void 0)}end(t,e,s){const i=(t?.plain??"").length;if(t===this.utterance&&this.pausedAt===void 0&&i>=40&&s>0){const r=(performance.now()-this.startedAt)/1e3;r>0&&this.speeds.set(e,i/r/s)}this.reset()}reset(){this.utterance=void 0,this.pausedAt=void 0}get speaking(){return this.utterance!==void 0&&this.pausedAt===void 0}elapsed(){return this.utterance?((this.pausedAt??performance.now())-this.startedAt)/1e3:0}speed(t,e){return(this.speeds.get(t)??12)*e}}export{a as SpeechProgress};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ensureEnumValue as l,ensureBoolean as p,ensureDecorationStyle as e}from"../../preferences/guards.js";import{ReadAloudAutoPause as t}from"./ReadAloudPreferences.js";import{DecorationStyleType as n}from"@readium/decorator";class m{constructor(o={}){const{autoPause:a,speakInContentLanguage:s,utteranceStyle:r,wordStyle:u,...i}=o;this.speech={segmentation:"sentence",skip:["pagebreak"],...i},this.autoPause=l(a,t)||t.none,this.speakInContentLanguage=p(s)??!1,this.utteranceStyle=e(r)??{type:n.Highlight},this.wordStyle=e(u)??{type:n.Underline}}}export{m as ReadAloudDefaults};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{SpeechPreferences as o}from"@readium/speech";import{ensureEnumValue as r,ensureBoolean as u,ensureDecorationStyle as a}from"../../preferences/guards.js";const c={none:"none",utterance:"utterance",block:"block",page:"page",spread:"spread"};class i{constructor(e={}){const{speakInContentLanguage:n,...s}=e,t=new o({...s,autoPause:void 0});this.format=t.format,this.inlineContextualization=t.inlineContextualization,this.verbosity=t.verbosity,this.skip=t.skip,this.contextualize=t.contextualize,this.language=t.language,this.segmentation=t.segmentation,this.pauseDuration=t.pauseDuration,this.autoPause=r(e.autoPause,c),this.speakInContentLanguage=u(n),this.rate=t.rate,this.pitch=t.pitch,this.volume=t.volume,this.utteranceStyle=a(e.utteranceStyle),this.wordStyle=a(e.wordStyle)}static serialize(e){const{...n}=e;return JSON.stringify(n)}static deserialize(e){try{const n=JSON.parse(e);return new i(n)}catch(n){return console.error("Failed to deserialize preferences:",n),null}}merging(e){const n={...this};for(const s of Object.keys(e))e[s]!==void 0&&(n[s]=e[s]);return new i(n)}}export{c as ReadAloudAutoPause,i as ReadAloudPreferences};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Layout as s}from"@readium/shared";import{SpeechPreferencesEditor as h,SpeechPreferences as c}from"@readium/speech";import{EnumPreference as g,BooleanPreference as p,Preference as u}from"../../preferences/Preference.js";import{ReadAloudPreferences as a,ReadAloudAutoPause as t}from"./ReadAloudPreferences.js";class S{constructor(e,n,r,i){const{speakInContentLanguage:o,...l}=e;this.speech=new h(new c({...l,autoPause:void 0}),r),this.own=new a({autoPause:e.autoPause,speakInContentLanguage:o,utteranceStyle:e.utteranceStyle,wordStyle:e.wordStyle}),this.settings=n,this.layout=i}get preferences(){return new a({...this.speech.preferences,autoPause:this.own.autoPause,speakInContentLanguage:this.own.speakInContentLanguage,utteranceStyle:this.own.utteranceStyle,wordStyle:this.own.wordStyle})}clear(){this.speech.clear(),this.own=new a({autoPause:null,speakInContentLanguage:null,utteranceStyle:null,wordStyle:null})}updatePreference(e,n){this.own[e]=n}get format(){return this.speech.format}get inlineContextualization(){return this.speech.inlineContextualization}get verbosity(){return this.speech.verbosity}get skip(){return this.speech.skip}get contextualize(){return this.speech.contextualize}get language(){return this.speech.language}get segmentation(){return this.speech.segmentation}get pauseDuration(){return this.speech.pauseDuration}get rate(){return this.speech.rate}get pitch(){return this.speech.pitch}get volume(){return this.speech.volume}get autoPause(){return new g({initialValue:this.own.autoPause,effectiveValue:this.settings.autoPause,isEffective:this.layout===s.fixed||this.settings.autoPause!==t.spread&&(this.layout===s.reflowable||this.settings.autoPause!==t.page),onChange:e=>{this.updatePreference("autoPause",e??null)},supportedValues:Object.values(t).filter(e=>e!==t.spread||this.layout===s.fixed)})}get speakInContentLanguage(){return new p({initialValue:this.own.speakInContentLanguage,effectiveValue:this.settings.speakInContentLanguage,isEffective:this.settings.language!=="none",onChange:e=>{this.updatePreference("speakInContentLanguage",e??null)}})}get utteranceStyle(){return new u({initialValue:this.own.utteranceStyle,effectiveValue:this.settings.utteranceStyle,isEffective:!0,onChange:e=>{this.updatePreference("utteranceStyle",e??null)}})}get wordStyle(){return new u({initialValue:this.own.wordStyle,effectiveValue:this.settings.wordStyle,isEffective:!0,onChange:e=>{this.updatePreference("wordStyle",e??null)}})}}export{S as ReadAloudPreferencesEditor};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class o{constructor(t,a,i){this.format=t.format,this.inlineContextualization=t.inlineContextualization,this.verbosity=t.verbosity,this.skip=t.skip,this.contextualize=t.contextualize,this.language=t.language,this.segmentation=t.segmentation,this.pauseDuration=t.pauseDuration,this.autoPause=a.autoPause??i.autoPause,this.speakInContentLanguage=a.speakInContentLanguage??i.speakInContentLanguage,this.rate=t.rate,this.pitch=t.pitch,this.volume=t.volume,this.utteranceStyle=a.utteranceStyle??i.utteranceStyle,this.wordStyle=a.wordStyle??i.wordStyle}}export{o as ReadAloudSettings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Loader as o}from"@readium/navigator-html-injectables";import{FrameComms as n}from"../epub/frame/FrameComms.js";import{sML as h}from"@readium/helpers";import{KeyboardConditionBridge as a}from"../peripherals/KeyboardConditionBridge.js";import{createSerializer as c}from"../helpers/serialize.js";class
|
|
1
|
+
import{Loader as o}from"@readium/navigator-html-injectables";import{FrameComms as n}from"../epub/frame/FrameComms.js";import{sML as h}from"@readium/helpers";import{KeyboardConditionBridge as a}from"../peripherals/KeyboardConditionBridge.js";import{createSerializer as c}from"../helpers/serialize.js";class u{constructor(t,i={},s=[],e=[],r=[]){this.timelineFragmentIds=e,this.hidden=!0,this.destroyed=!1,this.pendingUnwatchSelectors=[],this.currModules=[],this.serialize=c(),this.frame=document.createElement("iframe"),this.frame.classList.add("readium-navigator-iframe"),this.frame.style.visibility="hidden",this.frame.ariaHidden="true",this.frame.style.opacity="0",this.frame.style.position="absolute",this.frame.style.pointerEvents="none",this.frame.style.transition="visibility 0s, opacity 0.1s linear",this.frame.style.backgroundColor="#FFFFFF",this.source=t,this.contentProtectionConfig={...i},this.keyboardPeripheralsConfig=[...s],this.resizeWatchSelectors=[...r]}async load(t=[]){return this.serialize(()=>new Promise((i,s)=>{if(this.loader){const e=this.frame.contentWindow;if([...this.currModules].sort().join("|")===[...t].sort().join("|")){try{i(e)}catch{}return}this.comms?.halt(),this.loader.destroy(),this.loader=new o(e,t),this.currModules=t,this.comms=void 0;try{i(e)}catch{}return}this.frame.onload=()=>{const e=this.frame.contentWindow;this.loader=new o(e,t),this.currModules=t;try{i(e)}catch{}},this.frame.onerror=e=>{try{s(e)}catch{}},this.frame.contentWindow.location.replace(this.source)}))}applyContentProtection(){this.comms||this.comms.resume(),this.comms.send("peripherals_protection",this.contentProtectionConfig),this.keyboardPeripheralsConfig&&this.keyboardPeripheralsConfig.length>0&&(this.conditionBridge?.destroy(),this.conditionBridge=new a(this.keyboardPeripheralsConfig,t=>{t.length>0&&this.comms.send("keyboard_peripherals",t)}),this.conditionBridge.setup()),this.contentProtectionConfig.monitorScrollingExperimental&&this.comms.send("scroll_protection",{}),this.contentProtectionConfig.protectPrinting?.disable&&this.comms.send("print_protection",this.contentProtectionConfig.protectPrinting),this.resizeWatchSelectors.forEach(t=>{this.comms.send("decoration_resize",{action:"watch",selector:t})}),this.pendingUnwatchSelectors.forEach(t=>{this.comms.send("decoration_resize",{action:"unwatch",selector:t})}),this.pendingUnwatchSelectors=[]}addResizeTarget(t){this.resizeWatchSelectors.includes(t)||this.resizeWatchSelectors.push(t),this.pendingUnwatchSelectors=this.pendingUnwatchSelectors.filter(i=>i!==t),this.comms?.ready&&this.comms.send("decoration_resize",{action:"watch",selector:t})}removeResizeTarget(t){this.resizeWatchSelectors=this.resizeWatchSelectors.filter(i=>i!==t),this.comms?.ready?this.comms.send("decoration_resize",{action:"unwatch",selector:t}):this.pendingUnwatchSelectors.includes(t)||this.pendingUnwatchSelectors.push(t)}async destroy(){return this.serialize(async()=>{this.conditionBridge?.destroy(),await this.hideNow(),this.loader?.destroy(),this.frame.remove(),this.destroyed=!0})}async hide(){return this.serialize(()=>this.hideNow())}async hideNow(){if(!this.destroyed){if(this.frame.style.visibility="hidden",this.frame.ariaHidden="true",this.frame.style.opacity="0",this.frame.style.pointerEvents="none",this.hidden=!0,this.frame.parentElement)return this.comms===void 0||!this.comms.ready?void 0:new Promise((t,i)=>{this.comms?.send("unfocus",void 0,s=>{this.comms?.halt(),t()})});this.comms?.halt()}}async show(t){return this.serialize(()=>this.showNow(t))}async showNow(t){if(this.destroyed)throw Error("Trying to show frame when it doesn't exist");if(!this.frame.parentElement)throw Error("Trying to show frame that is not attached to the DOM");return this.comms?this.comms.resume():this.comms=new n(this.frame.contentWindow,this.source),new Promise((i,s)=>{this.comms?.send("activate",void 0,()=>{this.comms?.send("focus",void 0,()=>{this.applyContentProtection(),this.timelineFragmentIds.length>0&&this.comms?.send("timeline_entries",this.timelineFragmentIds);const e=()=>{this.frame.style.removeProperty("visibility"),this.frame.ariaHidden=null,this.frame.style.removeProperty("opacity"),this.frame.style.removeProperty("pointer-events"),this.hidden=!1,h.UA.WebKit&&this.comms?.send("force_webkit_recalc",void 0),i()};t!==void 0?this.comms?.send("go_progression",t,e):e()})})})}setCSSProperties(t){this.destroyed||!this.frame.contentWindow||(this.hidden&&!this.comms&&(this.comms=new n(this.frame.contentWindow,this.source),this.comms.halt()),this.comms?.send("update_properties",t))}get iframe(){if(this.destroyed)throw Error("Trying to use frame when it doesn't exist");return this.frame}get realSize(){if(this.destroyed)throw Error("Trying to use frame client rect when it doesn't exist");return this.frame.getBoundingClientRect()}get isDestroyed(){return this.destroyed}get window(){if(this.destroyed||!this.frame.contentWindow)throw Error("Trying to use frame window when it doesn't exist");return this.frame.contentWindow}get msg(){return this.comms}get ldr(){return this.loader}}export{u as WebPubFrameManager};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{WebPubBlobBuilder as w}from"./WebPubBlobBuilder.js";import{WebPubFrameManager as y}from"./WebPubFrameManager.js";class R{constructor(e,i,s,n={},o=[],r,h=[]){this.pool=new Map,this.blobs=new Map,this.inprogress=new Map,this.pendingUpdates=new Map,this.injector=null,this.container=e,this.currentCssProperties=i,this.injector=s,this.contentProtectionConfig=n,this.keyboardPeripheralsConfig=[...o],this.getFragmentIds=r??(()=>[]),this.resizeWatchSelectors=[...h]}addResizeTarget(e){this.resizeWatchSelectors.includes(e)||this.resizeWatchSelectors.push(e),this.pool.forEach(i=>i.addResizeTarget(e))}removeResizeTarget(e){this.resizeWatchSelectors=this.resizeWatchSelectors.filter(i=>i!==e),this.pool.forEach(i=>i.removeResizeTarget(e))}async destroy(){let e=this.inprogress.values(),i=e.next();const s=[];for(;i.value;)s.push(i.value),i=e.next();s.length>0&&await Promise.allSettled(s),this.inprogress.clear();let n=this.pool.values(),o=n.next();for(;o.value;)await o.value.destroy(),o=n.next();this.pool.clear(),this.blobs.forEach(r=>{this.injector?.releaseBlobUrl?.(r),URL.revokeObjectURL(r)}),this.blobs.clear(),this.injector?.dispose(),this.container.childNodes.forEach(r=>{(r.nodeType===Node.ELEMENT_NODE||r.nodeType===Node.TEXT_NODE)&&r.remove()})}async update(e,i,s){const n=e.readingOrder.items;let o=n.findIndex(f=>f.href===i.href);if(o<0)throw Error(`Locator not found in reading order: ${i.href}`);const r=n[o].href;this.inprogress.has(r)&&await this.inprogress.get(r);const h=new Promise(async(f,u)=>{const g=[],d=[];e.readingOrder.items.forEach((t,l)=>{l!==o&&l!==o-1&&l!==o+1&&(g.includes(t.href)||g.push(t.href)),l===o&&(d.includes(t.href)||d.push(t.href))}),g.forEach(async t=>{d.includes(t)||this.pool.has(t)&&(await this.pool.get(t)?.destroy(),this.pool.delete(t))}),this.currentBaseURL!==void 0&&e.baseURL!==this.currentBaseURL&&(this.blobs.forEach(t=>{this.injector?.releaseBlobUrl?.(t),URL.revokeObjectURL(t)}),this.blobs.clear()),this.currentBaseURL=e.baseURL;const b=async t=>{if(this.pendingUpdates.has(t)&&this.pendingUpdates.get(t)?.inPool===!1){const c=this.blobs.get(t);c&&(this.injector?.releaseBlobUrl?.(c),URL.revokeObjectURL(c),this.blobs.delete(t),this.pendingUpdates.delete(t))}if(this.pool.has(t)){const c=this.pool.get(t);if(!this.blobs.has(t))await c.destroy(),this.pool.delete(t),this.pendingUpdates.delete(t);else{await c.load(s);return}}const l=e.readingOrder.findWithHref(t);if(!l)return;if(!this.blobs.has(t)){const m=await new w(e,this.currentBaseURL||"",l,{cssProperties:this.currentCssProperties,injector:this.injector}).build();this.blobs.set(t,m)}const p=new y(this.blobs.get(t),this.contentProtectionConfig,this.keyboardPeripheralsConfig,this.getFragmentIds(t),this.resizeWatchSelectors);t!==r&&await p.hide(),this.container.appendChild(p.iframe),await p.load(s),this.pool.set(t,p)};try{await Promise.all(d.map(t=>b(t)))}catch(t){u(t)}const a=this.pool.get(r);if(a?.source!==this._currentFrame?.source&&(await this._currentFrame?.hide(),a&&await a.load(s),a&&await a.show(i.locations.progression),this._currentFrame=a,a)){const t=this.container.ownerDocument.activeElement;t&&t.tagName==="IFRAME"&&t!==a.iframe&&a.iframe.focus({preventScroll:!0})}f()});this.inprogress.set(r,h);try{await h}finally{this.inprogress.delete(r)}}setCSSProperties(e){if(!((s,n)=>{const o=Object.keys(s),r=Object.keys(n);if(o.length!==r.length)return!1;for(const h of o)if(s[h]!==n[h])return!1;return!0})(this.currentCssProperties||{},e)){this.currentCssProperties=e,this.pool.forEach(s=>{s.setCSSProperties(e)});for(const s of this.blobs.keys())this.pendingUpdates.set(s,{inPool:this.pool.has(s)})}}get currentFrames(){return[this._currentFrame]}get currentBounds(){const e={x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0,toJSON(){return this}};return this.currentFrames.forEach(i=>{if(!i)return;const s=i.realSize;e.x=Math.min(e.x,s.x),e.y=Math.min(e.y,s.y),e.width+=s.width,e.height=Math.max(e.height,s.height),e.top=Math.min(e.top,s.top),e.right=Math.min(e.right,s.right),e.bottom=Math.min(e.bottom,s.bottom),e.left=Math.min(e.left,s.left)}),e}}export{R as WebPubFramePoolManager};
|
|
1
|
+
import{WebPubBlobBuilder as w}from"./WebPubBlobBuilder.js";import{WebPubFrameManager as y}from"./WebPubFrameManager.js";class R{constructor(e,i,s,n={},o=[],r,h=[]){this.pool=new Map,this.blobs=new Map,this.inprogress=new Map,this.pendingUpdates=new Map,this.injector=null,this.container=e,this.currentCssProperties=i,this.injector=s,this.contentProtectionConfig=n,this.keyboardPeripheralsConfig=[...o],this.getFragmentIds=r??(()=>[]),this.resizeWatchSelectors=[...h]}addResizeTarget(e){this.resizeWatchSelectors.includes(e)||this.resizeWatchSelectors.push(e),this.pool.forEach(i=>i.addResizeTarget(e))}removeResizeTarget(e){this.resizeWatchSelectors=this.resizeWatchSelectors.filter(i=>i!==e),this.pool.forEach(i=>i.removeResizeTarget(e))}async destroy(){let e=this.inprogress.values(),i=e.next();const s=[];for(;i.value;)s.push(i.value),i=e.next();s.length>0&&await Promise.allSettled(s),this.inprogress.clear();let n=this.pool.values(),o=n.next();for(;o.value;)await o.value.destroy(),o=n.next();this.pool.clear(),this.blobs.forEach(r=>{this.injector?.releaseBlobUrl?.(r),URL.revokeObjectURL(r)}),this.blobs.clear(),this.injector?.dispose(),this.container.childNodes.forEach(r=>{(r.nodeType===Node.ELEMENT_NODE||r.nodeType===Node.TEXT_NODE)&&r.remove()})}async update(e,i,s){const n=e.readingOrder.items;let o=n.findIndex(f=>f.href===i.href);if(o<0)throw Error(`Locator not found in reading order: ${i.href}`);const r=n[o].href;this.inprogress.has(r)&&await this.inprogress.get(r);const h=new Promise(async(f,u)=>{const g=[],d=[];e.readingOrder.items.forEach((t,l)=>{l!==o&&l!==o-1&&l!==o+1&&(g.includes(t.href)||g.push(t.href)),l===o&&(d.includes(t.href)||d.push(t.href))}),g.forEach(async t=>{d.includes(t)||this.pool.has(t)&&(await this.pool.get(t)?.destroy(),this.pool.delete(t))}),this.currentBaseURL!==void 0&&e.baseURL!==this.currentBaseURL&&(this.blobs.forEach(t=>{this.injector?.releaseBlobUrl?.(t),URL.revokeObjectURL(t)}),this.blobs.clear()),this.currentBaseURL=e.baseURL;const b=async t=>{if(this.pendingUpdates.has(t)&&this.pendingUpdates.get(t)?.inPool===!1){const c=this.blobs.get(t);c&&(this.injector?.releaseBlobUrl?.(c),URL.revokeObjectURL(c),this.blobs.delete(t),this.pendingUpdates.delete(t))}if(this.pool.has(t)){const c=this.pool.get(t);if(!this.blobs.has(t))await c.destroy(),this.pool.delete(t),this.pendingUpdates.delete(t);else{await c.load(s);return}}const l=e.readingOrder.findWithHref(t);if(!l)return;if(!this.blobs.has(t)){const m=await new w(e,this.currentBaseURL||"",l,{cssProperties:this.currentCssProperties,injector:this.injector}).build();this.blobs.set(t,m)}const p=new y(this.blobs.get(t),this.contentProtectionConfig,this.keyboardPeripheralsConfig,this.getFragmentIds(t),this.resizeWatchSelectors);t!==r&&await p.hide(),this.container.appendChild(p.iframe),await p.load(s),this.pool.set(t,p)};try{await Promise.all(d.map(t=>b(t)))}catch(t){u(t)}const a=this.pool.get(r);if(a?.source!==this._currentFrame?.source&&(await this._currentFrame?.hide(),a&&await a.load(s),a&&await a.show(i.locations.progression),this._currentFrame=a,a)){const t=this.container.ownerDocument.activeElement;t&&t.tagName==="IFRAME"&&t!==a.iframe&&a.iframe.focus({preventScroll:!0})}f()});this.inprogress.set(r,h);try{await h}finally{this.inprogress.delete(r)}}setCSSProperties(e){if(!((s,n)=>{const o=Object.keys(s),r=Object.keys(n);if(o.length!==r.length)return!1;for(const h of o)if(s[h]!==n[h])return!1;return!0})(this.currentCssProperties||{},e)){this.currentCssProperties=e,this.pool.forEach(s=>{s.setCSSProperties(e)});for(const s of this.blobs.keys())this.pendingUpdates.set(s,{inPool:this.pool.has(s)})}}get currentFrames(){return[this._currentFrame]}_frameFor(e){return this.pool.get(e)}get currentBounds(){const e={x:0,y:0,width:0,height:0,top:0,right:0,bottom:0,left:0,toJSON(){return this}};return this.currentFrames.forEach(i=>{if(!i)return;const s=i.realSize;e.x=Math.min(e.x,s.x),e.y=Math.min(e.y,s.y),e.width+=s.width,e.height=Math.max(e.height,s.height),e.top=Math.min(e.top,s.top),e.right=Math.min(e.right,s.right),e.bottom=Math.min(e.bottom,s.bottom),e.left=Math.min(e.left,s.left)}),e}}export{R as WebPubFramePoolManager};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Feature as w,Link as u,Locator as f,LocatorText as P,getCssSelector as y,getHtmlId as S,LocatorLocations as k}from"@readium/shared";import{VisualNavigator as x}from"../Navigator.js";import{WebPubFramePoolManager as D}from"./WebPubFramePoolManager.js";import{WebPubModules as C}from"@readium/navigator-html-injectables";import{p as g}from"../_virtual/index.js";import{getScriptMode as I}from"../helpers/scriptMode.js";import{WebPubCSS as O}from"./css/WebPubCSS.js";import{WebUserProperties as E,WebRSProperties as F}from"./css/Properties.js";import{WebPubPreferences as A}from"./preferences/WebPubPreferences.js";import{WebPubDefaults as T}from"./preferences/WebPubDefaults.js";import{WebPubSettings as _}from"./preferences/WebPubSettings.js";import{WebPubPreferencesEditor as v}from"./preferences/WebPubPreferencesEditor.js";import{Injector as W}from"../injection/Injector.js";import{createReadiumWebPubRules as M}from"../injection/webpubInjectables.js";import{NavigatorProtector as R,NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as b}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as H,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as L}from"../peripherals/KeyboardPeripherals.js";import{supportsDecorationStyle as N,decorationsEqual as z,resolveDecorationForWire as m}from"@readium/decorator";const V=h=>({frameLoaded:h.frameLoaded||(()=>{}),positionChanged:h.positionChanged||(()=>{}),timelineItemChanged:h.timelineItemChanged||(()=>{}),tap:h.tap||(()=>!1),click:h.click||(()=>!1),zoom:h.zoom||(()=>{}),scroll:h.scroll||(()=>{}),customEvent:h.customEvent||(()=>{}),handleLocator:h.handleLocator||(()=>!1),textSelected:h.textSelected||(()=>{}),contentProtection:h.contentProtection||(()=>{}),contextMenu:h.contextMenu||(()=>{}),peripheral:h.peripheral||(()=>{})});function j(h,e){return h.length===e.length&&h.every((t,i)=>t===e[i])}class B extends x{constructor(e,t,i,r=void 0,o={preferences:{},defaults:{}}){super(),this.currentIndex=0,this._destroyed=!1,this._visibleFragmentIds=[],this._notifiedVisibleFragmentIds=[],this._preferencesEditor=null,this._injector=null,this._isNavigating=!1,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._decorations=new Map,this._decorationObservers=new Map,this._decorationHoveredDecorations=new Map,this._decorationActivationState=new Map,this._decorationHoverState=new Map,this._decorationActivationConsumed=!1,this.webViewport={readingOrder:[],progressions:new Map,positions:null},this.pub=t,this.container=e,this.listeners=V(i),this._preferences=new A(o.preferences),this._defaults=new T(o.defaults),this._settings=new _(this._preferences,this._defaults,this.hasDisplayTransformability),this._css=new O({rsProperties:new F({experiments:this._settings.experiments||null}),userProperties:new E({zoom:this._settings.zoom})});const s=M(t.readingOrder.items),l=o.injectables||{rules:[],allowedDomains:[]};if(this._injector=new W({rules:[...s,...l.rules],allowedDomains:l.allowedDomains}),this._contentProtection=o.contentProtection||{},this._decoratorConfig=o.decoratorConfig||{},this._decorationResizeSelectors=new Set(this._decoratorConfig.resizeWatchSelectors??[]),this._keyboardPeripherals=this.mergeKeyboardPeripherals(this._contentProtection,o.keyboardPeripherals||[]),(this._contentProtection.disableContextMenu||this._contentProtection.checkAutomation||this._contentProtection.checkIFrameEmbedding||this._contentProtection.monitorDevTools||this._contentProtection.protectPrinting?.disable)&&(this._navigatorProtector=new R(this._contentProtection),this._suspiciousActivityListener=a=>{const{type:n,...c}=a.detail;n==="context_menu"?this.listeners.contextMenu(c):this.listeners.contentProtection(n,c)},window.addEventListener(b,this._suspiciousActivityListener)),this._keyboardPeripherals.length>0&&(this._keyboardPeripheralsManager=new H({keyboardPeripherals:this._keyboardPeripherals}),this._keyboardPeripheralListener=a=>{const n=a.detail;this.listeners.peripheral(n)},window.addEventListener(L,this._keyboardPeripheralListener)),r&&typeof r.copyWithLocations=="function"){this.currentLocation=r;const a=this.pub.readingOrder.findIndexWithHref(r.href);a>=0&&(this.currentIndex=a)}else this.currentLocation=this.createCurrentLocator()}async load(){if(await this.updateCSS(!1),this._destroyed)return;const e=this.compileCSSProperties(this._css);this.framePool=new D(this.container,e,this._injector,this._contentProtection,this._keyboardPeripherals,t=>this.pub.timeline.segmentsForHref(t).flatMap(i=>i.references).map(i=>{const r=i.indexOf("#");return r>=0?i.slice(r+1):""}).filter(Boolean),[...this._decorationResizeSelectors]),!this._destroyed&&(this.currentLocation=this.completeLocator(this.currentLocation),await this.apply())}get settings(){return Object.freeze({...this._settings})}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new v(this._preferences,this.settings,this.pub.metadata)),this._preferencesEditor}async submitPreferences(e){this._preferences=this._preferences.merging(e),await this.applyPreferences()}async applyPreferences(){this._settings=new _(this._preferences,this._defaults,this.hasDisplayTransformability),this._preferencesEditor!==null&&(this._preferencesEditor=new v(this._preferences,this.settings,this.pub.metadata)),await this.updateCSS(!0)}async updateCSS(e){this._css.update(this._settings),e&&await this.commitCSS(this._css)}compileCSSProperties(e){const t={};for(const[i,r]of Object.entries(e.rsProperties.toCSSProperties()))t[i]=r;for(const[i,r]of Object.entries(e.userProperties.toCSSProperties()))t[i]=r;return t}async commitCSS(e){const t=this.compileCSSProperties(e);this.framePool.setCSSProperties(t)}get _cframes(){return this.framePool.currentFrames}get hasDisplayTransformability(){return this.pub.metadata?.accessibility?.feature?.some(e=>e.value===w.DISPLAY_TRANSFORMABILITY.value)??!1}eventListener(e,t){switch(e){case"_pong":this.listeners.frameLoaded(this.framePool.currentFrames[0].iframe.contentWindow),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),this._reapplyDecorationsToCurrentFrame();break;case"first_visible_locator":const i=f.deserialize(t);if(!i)break;this.currentLocation=new f({href:this.currentLocation.href,type:this.currentLocation.type,title:this.currentLocation.title,locations:i?.locations,text:i?.text}),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation);break;case"text_selected":{const a=t;a.locator=new f({href:this.currentLocation.href,type:this.currentLocation.type,text:new P({highlight:a.text})}),this.listeners.textSelected(a);break}case"decoration_activated":{this._handleDecorationActivated(t)&&(this._decorationActivationConsumed=!0);break}case"decoration_pointer_enter":this._handleDecorationPointerEnter(t);break;case"decoration_pointer_leave":this._handleDecorationPointerLeave(t);break;case"click":case"tap":if(this._decorationActivationConsumed){this._decorationActivationConsumed=!1;break}const r=t;if(r.interactiveElement){const a=new DOMParser().parseFromString(r.interactiveElement,"text/html").body.children[0];if(a.nodeType===a.ELEMENT_NODE&&a.nodeName==="A"&&a.hasAttribute("href")){const n=a.attributes.getNamedItem("href")?.value;if(n.startsWith("#"))this.go(this.currentLocation.copyWithLocations({fragments:[n.substring(1)]}),!1,()=>{});else if(n.startsWith("mailto:")||n.startsWith("tel:"))this.listeners.handleLocator(new u({href:n}).locator);else try{let c;if(n.startsWith("http://")||n.startsWith("https://"))c=n;else if(this.currentLocation.href.startsWith("http://")||this.currentLocation.href.startsWith("https://")){const p=new URL(this.currentLocation.href);c=new URL(n,p).href}else c=g.join(g.dirname(this.currentLocation.href),n);const d=this.pub.readingOrder.findWithHref(c);d?this.goLink(d,!1,()=>{}):(console.warn(`Internal link not found in readingOrder: ${c}`),this.listeners.handleLocator(new u({href:n}).locator))}catch(c){console.warn(`Couldn't resolve internal link for ${n}: ${c}`),this.listeners.handleLocator(new u({href:n}).locator)}}else console.log("Clicked on",a)}else if(e==="click"?this.listeners.click(r):this.listeners.tap(r))break;break;case"scroll":this.listeners.scroll(t);break;case"zoom":this.listeners.zoom(t);break;case"progress":this.syncLocation(t);break;case"content_protection":const o=t;this.listeners.contentProtection(o.type,o);break;case"context_menu":this.listeners.contextMenu(t);break;case"keyboard_peripherals":const s=t,l={...s,interactiveElement:void 0};s.interactiveElement&&(l.interactiveElement=new DOMParser().parseFromString(s.interactiveElement,"text/html").body.children[0]),this.listeners.peripheral(l);break;case"log":console.log(this.framePool.currentFrames[0]?.source?.split("/")[3],...t);break;default:this.listeners.customEvent(e,t);break}}determineModules(){const e=C.slice(),t=I(this.pub.metadata);return t==="cjk-vertical"||t==="mongolian-vertical"?e.map(i=>i==="webpub_snapper"?"cjk_vertical_snapper":i):e}attachListener(){this.framePool.currentFrames[0]?.msg&&(this.framePool.currentFrames[0].msg.listener=(e,t)=>{this.eventListener(e,t)}),this._reapplyDecorationsToCurrentFrame()}async apply(){if(await this.framePool.update(this.pub,this.currentLocation,this.determineModules()),this.attachListener(),this.pub.readingOrder.findIndexWithHref(this.currentLocation.href)<0)throw Error("Link for "+this.currentLocation.href+" not found!")}async destroy(){this._destroyed=!0,this._suspiciousActivityListener&&window.removeEventListener(b,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(L,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardPeripheralsManager?.destroy(),await this.framePool?.destroy(),this._decorations.clear(),this._decorationObservers.clear(),this._decorationHoveredDecorations.clear(),this._decorationActivationState.clear(),this._decorationHoverState.clear(),this._decorationResizeSelectors.clear()}supportsDecorationStyle(e){return N(e,this._decoratorConfig.decorationTemplates)}registerDecorationObserver(e,t){this._decorationObservers.has(e)||this._decorationObservers.set(e,new Set),this._decorationObservers.get(e).add(t),t.onDecorationActivated&&(this._decorationActivationState.set(e,!0),this._sendDecorationActivatable(e,!0)),(t.onDecorationPointerEnter||t.onDecorationPointerLeave)&&(this._decorationHoverState.set(e,!0),this._sendDecorationHoverable(e,!0))}unregisterDecorationObserver(e){this._decorationObservers.forEach((t,i)=>{if(!t.has(e))return;t.delete(e);const r=[...t].some(s=>s.onDecorationActivated);this._decorationActivationState.has(i)&&!r&&(this._decorationActivationState.delete(i),this._sendDecorationActivatable(i,!1));const o=[...t].some(s=>s.onDecorationPointerEnter||s.onDecorationPointerLeave);this._decorationHoverState.has(i)&&!o&&(this._decorationHoverState.delete(i),this._sendDecorationHoverable(i,!1))})}_sendDecorationActivatable(e,t){const i=this.framePool?.currentFrames[0];i?.msg&&i.msg.send("decoration_activatable",{group:e,activatable:t})}_sendDecorationHoverable(e,t){const i=this.framePool?.currentFrames[0];i?.msg&&i.msg.send("decoration_hoverable",{group:e,hoverable:t})}addDecorationResizeTarget(e){this._decorationResizeSelectors.add(e),this.framePool?.addResizeTarget(e)}removeDecorationResizeTarget(e){this._decorationResizeSelectors.delete(e),this.framePool?.removeResizeTarget(e)}applyDecorations(e,t){const i=this._decorations.get(t)??[],r=new Map(i.map(d=>[d.id,d])),o=new Map(e.map(d=>[d.id,d])),s=[],l=[],a=[];for(const[d,p]of r)o.has(d)?z(p,o.get(d))||a.push(o.get(d)):s.push(d);for(const[d,p]of o)r.has(d)||l.push(p);this._decorations.set(t,e),this._sendDecorationOps(t,s,l,a,i);const n=this._decorationActivationState.get(t);n!==void 0&&this._sendDecorationActivatable(t,n);const c=this._decorationHoverState.get(t);c!==void 0&&this._sendDecorationHoverable(t,c)}_sendDecorationOps(e,t,i,r,o){const s=this.framePool?.currentFrames[0];if(!s?.msg)return;const l=this.currentLocation.href,a=new Map(o.map(n=>[n.id,n]));for(const n of t){const c=a.get(n);!c||c.locator.href!==l||s.msg.send("decorate",{group:e,action:"remove",decoration:{id:n}})}for(const n of i)n.locator.href===l&&s.msg.send("decorate",{group:e,action:"add",decoration:m(n,this._decoratorConfig.decorationTemplates)});for(const n of r)n.locator.href===l&&s.msg.send("decorate",{group:e,action:"update",decoration:m(n,this._decoratorConfig.decorationTemplates)})}_reapplyDecorationsToCurrentFrame(){const e=this.framePool?.currentFrames[0];if(!e?.msg)return;const t=this.currentLocation.href;for(const[i,r]of this._decorations){const o=r.filter(s=>s.locator.href===t);if(o.length!==0){e.msg.send("decorate",{group:i,action:"clear"});for(const s of o)e.msg.send("decorate",{group:i,action:"add",decoration:m(s,this._decoratorConfig.decorationTemplates)})}}for(const[i,r]of this._decorationActivationState)e.msg.send("decoration_activatable",{group:i,activatable:r});for(const[i,r]of this._decorationHoverState)e.msg.send("decoration_hoverable",{group:i,hoverable:r})}_handleDecorationActivated(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return!1;const i=(this._decorations.get(e.group)??[]).find(s=>s.id===e.decorationId);if(!i)return!1;const r={decoration:i,group:e.group,rect:e.rect,point:e.point};let o=!1;for(const s of t)s.onDecorationActivated?.(r)&&(o=!0);return o}_handleDecorationPointerEnter(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId);if(!i)return;this._decorationHoveredDecorations.set(e.group,i);const r={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerEnter?.(r)}_handleDecorationPointerLeave(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId)??this._decorationHoveredDecorations.get(e.group);if(this._decorationHoveredDecorations.delete(e.group),!i)return;const r={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerLeave?.(r)}async changeResource(e){if(e===0)return!1;const t=this.pub.readingOrder.findIndexWithHref(this.currentLocation.href),i=Math.max(0,Math.min(this.pub.readingOrder.items.length-1,t+e));return i===t?!1:(this.currentIndex=i,this.currentLocation=this.createCurrentLocator(),await this.apply(),!0)}updateViewport(e){this.webViewport.readingOrder=[],this.webViewport.progressions.clear(),this.webViewport.positions=null,this.currentLocation&&(this.webViewport.readingOrder.push(this.currentLocation.href),this.webViewport.progressions.set(this.currentLocation.href,e),this.currentLocation.locations?.position!==void 0&&(this.webViewport.positions=[this.currentLocation.locations.position]))}async syncLocation(e){const t=e;this.currentLocation&&(this.currentLocation=this.currentLocation.copyWithLocations({progression:t.start})),this.updateViewport(t),this.listeners.positionChanged(this.currentLocation);const i=t.fragmentId?this.currentLocation.copyWithLocations({fragments:[`#${t.fragmentId}`]}):this.currentLocation;this._visibleFragmentIds=t.visibleFragmentIds??[],this._notifyTimelineChange(i),await this.framePool.update(this.pub,this.currentLocation,this.determineModules())}goBackward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this.changeResource(-1).then(i=>{this._isNavigating=!1,t(i)})}goForward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this.changeResource(1).then(i=>{this._isNavigating=!1,t(i)})}get currentLocator(){return this.currentLocation}get viewport(){return this.webViewport}get isScrollStart(){const e=this.viewport.readingOrder[0];return this.viewport.progressions.get(e)?.start===0}get isScrollEnd(){const e=this.viewport.readingOrder[this.viewport.readingOrder.length-1];return this.viewport.progressions.get(e)?.end===1}get canGoBackward(){const e=this.pub.readingOrder.items[0]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.start===0)}get canGoForward(){const e=this.pub.readingOrder.items[this.pub.readingOrder.items.length-1]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.end===1)}get readingProgression(){return this.pub.metadata.effectiveReadingProgression}get publication(){return this.pub}get timeline(){const e=this.pub.timeline;return this._wrappedTimeline||(this._wrappedTimeline=new Proxy(e,{get:(t,i)=>{if(i!=="navigableFrom"){const r=Reflect.get(t,i,t);return typeof r=="function"?r.bind(t):r}return r=>{const o=this._visibleFragmentIds;let s=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[0]}`]})):void 0)??r;const l=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[o.length-1]}`]})):void 0)??r;if(this.isScrollStart){const c=t.ancestors(s).find(d=>d.references.includes(this.currentLocation.href));c&&(s=c)}const a=t.navigableFrom(s).previous,n=t.navigableFrom(l).next;return{previous:a,next:n}}}})),this._wrappedTimeline}async loadLocator(e,t){let i=!1,r=y(e.locations);if(e.text?.highlight?i=await new Promise((a,n)=>{this.framePool.currentFrames[0].msg.send("go_text",r?[e.text?.serialize(),r]:e.text?.serialize(),c=>a(c))}):r&&(i=await new Promise((a,n)=>{this.framePool.currentFrames[0].msg.send("go_text",["",r],c=>a(c))})),i){t(i);return}const o=S(e.locations);if(o&&(i=await new Promise((a,n)=>{this.framePool.currentFrames[0].msg.send("go_id",o,c=>a(c))})),i){t(i);return}const s=e?.locations?.progression;s&&s>0?i=await new Promise((a,n)=>{this.framePool.currentFrames[0].msg.send("go_progression",s,c=>a(c))}):i=!0,t(i)}completeLocator(e){if(!e.href){const t=this.pub.readingOrder.items;let i=!1;if(typeof e.locations.position=="number"){const r=t[e.locations.position-1];r&&(e=(this.pub.manifest.locatorFromLink(r)||new f({href:r.href,type:r.type||"text/html"})).copyWithLocations(e.locations),i=!0)}if(!i&&typeof e.locations?.totalProgression=="number"){const r=e.locations.totalProgression,o=Math.min(t.length-1,Math.max(0,Math.round(r*(t.length-1)))),s=t[o];s&&(e=(this.pub.manifest.locatorFromLink(s)||new f({href:s.href,type:s.type||"text/html"})).copyWithLocations(e.locations))}}return e}go(e,t,i){e=this.completeLocator(e);const r=e.href.split("#")[0];if(!this.pub.readingOrder.findWithHref(r))return i(this.listeners.handleLocator(e));const s=this.pub.readingOrder.findIndexWithHref(r);if(s>=0&&(this.currentIndex=s),this._isNavigating){i(!1);return}this._isNavigating=!0,this.currentLocation=this.createCurrentLocator(),this.apply().then(()=>this.loadLocator(e,l=>{this._isNavigating=!1,i(l)})).then(()=>{this.attachListener()})}goLink(e,t,i){return this.go(e.locator,t,i)}createCurrentLocator(){const t=this.pub.readingOrder.items[this.currentIndex];if(!t)throw new Error("No current resource available");const r=this.currentLocation&&this.currentLocation.href===t.href&&this.currentLocation.locations.progression?this.currentLocation.locations.progression:0;return this.pub.manifest.locatorFromLink(t)||new f({href:t.href,type:t.type||"text/html",locations:new k({fragments:[],progression:r,position:this.currentIndex+1})})}_notifyTimelineChange(e){const t=this.timeline.locate(e),i=!j(this._visibleFragmentIds,this._notifiedVisibleFragmentIds);(t!==this._currentTimelineItem||i)&&(this._currentTimelineItem=t,this._notifiedVisibleFragmentIds=this._visibleFragmentIds,this.listeners.timelineItemChanged(t))}}const ce=B;export{ce as ExperimentalWebPubNavigator,B as WebPubNavigator};
|
|
1
|
+
import{Feature as P,Link as m,Locator as u,LocatorText as x,getCssSelector as g,getHtmlId as k,LocatorLocations as S}from"@readium/shared";import{VisualNavigator as I}from"../Navigator.js";import{WebPubFramePoolManager as C}from"./WebPubFramePoolManager.js";import{WebPubModules as D}from"@readium/navigator-html-injectables";import{p as v}from"../_virtual/index.js";import{getScriptMode as E}from"../helpers/scriptMode.js";import{WebPubCSS as F}from"./css/WebPubCSS.js";import{WebUserProperties as O,WebRSProperties as T}from"./css/Properties.js";import{WebPubPreferences as W}from"./preferences/WebPubPreferences.js";import{WebPubDefaults as A}from"./preferences/WebPubDefaults.js";import{WebPubSettings as b}from"./preferences/WebPubSettings.js";import{WebPubPreferencesEditor as L}from"./preferences/WebPubPreferencesEditor.js";import{Injector as R}from"../injection/Injector.js";import{createReadiumWebPubRules as M}from"../injection/webpubInjectables.js";import{NavigatorProtector as H,NAVIGATOR_SUSPICIOUS_ACTIVITY_EVENT as w}from"../protection/NavigatorProtector.js";import{KeyboardPeripherals as N,NAVIGATOR_KEYBOARD_PERIPHERAL_EVENT as y}from"../peripherals/KeyboardPeripherals.js";import{supportsDecorationStyle as z,decorationsEqual as V,resolveDecorationForWire as _}from"@readium/decorator";const j=1e3,U=d=>({frameLoaded:d.frameLoaded||(()=>{}),positionChanged:d.positionChanged||(()=>{}),timelineItemChanged:d.timelineItemChanged||(()=>{}),tap:d.tap||(()=>!1),click:d.click||(()=>!1),zoom:d.zoom||(()=>{}),scroll:d.scroll||(()=>{}),customEvent:d.customEvent||(()=>{}),handleLocator:d.handleLocator||(()=>!1),textSelected:d.textSelected||(()=>{}),contentProtection:d.contentProtection||(()=>{}),contextMenu:d.contextMenu||(()=>{}),peripheral:d.peripheral||(()=>{})});function B(d,e){return d.length===e.length&&d.every((t,i)=>t===e[i])}class q extends I{constructor(e,t,i,r=void 0,o={preferences:{},defaults:{}}){super(),this.currentIndex=0,this._destroyed=!1,this._visibleFragmentIds=[],this._notifiedVisibleFragmentIds=[],this._preferencesEditor=null,this._injector=null,this._isNavigating=!1,this._navigatorProtector=null,this._keyboardPeripheralsManager=null,this._suspiciousActivityListener=null,this._keyboardPeripheralListener=null,this._decorations=new Map,this._decorationObservers=new Map,this._decorationHoveredDecorations=new Map,this._decorationActivationState=new Map,this._decorationHoverState=new Map,this._decorationActivationConsumed=!1,this._navigationLocked=!1,this._pointedPieceRequests=new Map,this._pointedPieceRequestId=0,this.webViewport={readingOrder:[],progressions:new Map,positions:null},this.pub=t,this.container=e,this.listeners=U(i),this._preferences=new W(o.preferences),this._defaults=new A(o.defaults),this._settings=new b(this._preferences,this._defaults,this.hasDisplayTransformability),this._css=new F({rsProperties:new T({experiments:this._settings.experiments||null}),userProperties:new O({zoom:this._settings.zoom})});const n=M(t.readingOrder.items),l=o.injectables||{rules:[],allowedDomains:[]};if(this._injector=new R({rules:[...n,...l.rules],allowedDomains:l.allowedDomains}),this._contentProtection=o.contentProtection||{},this._decoratorConfig=o.decoratorConfig||{},this._decorationResizeSelectors=new Set(this._decoratorConfig.resizeWatchSelectors??[]),this._keyboardPeripherals=this.mergeKeyboardPeripherals(this._contentProtection,o.keyboardPeripherals||[]),(this._contentProtection.disableContextMenu||this._contentProtection.checkAutomation||this._contentProtection.checkIFrameEmbedding||this._contentProtection.monitorDevTools||this._contentProtection.protectPrinting?.disable)&&(this._navigatorProtector=new H(this._contentProtection),this._suspiciousActivityListener=c=>{const{type:a,...s}=c.detail;a==="context_menu"?this.listeners.contextMenu(s):this.listeners.contentProtection(a,s)},window.addEventListener(w,this._suspiciousActivityListener)),this._keyboardPeripherals.length>0&&(this._keyboardPeripheralsManager=new N({keyboardPeripherals:this._keyboardPeripherals}),this._keyboardPeripheralListener=c=>{const a=c.detail;this.listeners.peripheral(a)},window.addEventListener(y,this._keyboardPeripheralListener)),r&&typeof r.copyWithLocations=="function"){this.currentLocation=r;const c=this.pub.readingOrder.findIndexWithHref(r.href);c>=0&&(this.currentIndex=c)}else this.currentLocation=this.createCurrentLocator()}async load(){if(await this.updateCSS(!1),this._destroyed)return;const e=this.compileCSSProperties(this._css);this.framePool=new C(this.container,e,this._injector,this._contentProtection,this._keyboardPeripherals,t=>this.pub.timeline.segmentsForHref(t).flatMap(i=>i.references).map(i=>{const r=i.indexOf("#");return r>=0?i.slice(r+1):""}).filter(Boolean),[...this._decorationResizeSelectors]),!this._destroyed&&(this.currentLocation=this.completeLocator(this.currentLocation),await this.apply())}get settings(){return Object.freeze({...this._settings})}get preferencesEditor(){return this._preferencesEditor===null&&(this._preferencesEditor=new L(this._preferences,this.settings,this.pub.metadata)),this._preferencesEditor}async submitPreferences(e){this._preferences=this._preferences.merging(e),await this.applyPreferences()}async applyPreferences(){this._settings=new b(this._preferences,this._defaults,this.hasDisplayTransformability),this._preferencesEditor!==null&&(this._preferencesEditor=new L(this._preferences,this.settings,this.pub.metadata)),await this.updateCSS(!0)}async updateCSS(e){this._css.update(this._settings),e&&await this.commitCSS(this._css)}compileCSSProperties(e){const t={};for(const[i,r]of Object.entries(e.rsProperties.toCSSProperties()))t[i]=r;for(const[i,r]of Object.entries(e.userProperties.toCSSProperties()))t[i]=r;return t}async commitCSS(e){const t=this.compileCSSProperties(e);this.framePool.setCSSProperties(t)}get _cframes(){return this.framePool.currentFrames}get hasDisplayTransformability(){return this.pub.metadata?.accessibility?.feature?.some(e=>e.value===P.DISPLAY_TRANSFORMABILITY.value)??!1}eventListener(e,t,i){switch(e){case"_pong":this.listeners.frameLoaded(this.framePool.currentFrames[0].iframe.contentWindow),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation),this._reapplyDecorationsToCurrentFrame(),this._watchTextLayoutInCurrentFrame(!0),this._sendNavigationLock();break;case"text_layout":i&&i===this._textLayoutFrame&&this.currentLocation.href.split("#")[0]===this._textLayoutWatch?.href&&this._textLayoutWatch.cb(t);break;case"pointed_piece":{const{id:a,index:s}=t;this._pointedPieceRequests.get(a)?.(s);break}case"first_visible_locator":const r=u.deserialize(t);if(!r)break;this.currentLocation=new u({href:this.currentLocation.href,type:this.currentLocation.type,title:this.currentLocation.title,locations:r?.locations,text:r?.text}),this.listeners.positionChanged(this.currentLocation),this._notifyTimelineChange(this.currentLocation);break;case"text_selected":{const a=t;a.locator=new u({href:this.currentLocation.href,type:this.currentLocation.type,text:new x({highlight:a.text})}),this.listeners.textSelected(a);break}case"decoration_activated":{this._handleDecorationActivated(t)&&(this._decorationActivationConsumed=!0);break}case"decoration_pointer_enter":this._handleDecorationPointerEnter(t);break;case"decoration_pointer_leave":this._handleDecorationPointerLeave(t);break;case"click":case"tap":if(this._decorationActivationConsumed){this._decorationActivationConsumed=!1;break}const o=t;if(o.interactiveElement){const a=new DOMParser().parseFromString(o.interactiveElement,"text/html").body.children[0];if(a.nodeType===a.ELEMENT_NODE&&a.nodeName==="A"&&a.hasAttribute("href")){const s=a.attributes.getNamedItem("href")?.value;if(s.startsWith("#"))this._navigationLocked||this.go(this.currentLocation.copyWithLocations({fragments:[s.substring(1)]}),!1,()=>{});else if(s.startsWith("mailto:")||s.startsWith("tel:"))this.listeners.handleLocator(new m({href:s}).locator);else try{let h;if(s.startsWith("http://")||s.startsWith("https://"))h=s;else if(this.currentLocation.href.startsWith("http://")||this.currentLocation.href.startsWith("https://")){const p=new URL(this.currentLocation.href);h=new URL(s,p).href}else h=v.join(v.dirname(this.currentLocation.href),s);const f=this.pub.readingOrder.findWithHref(h);f?this._navigationLocked||this.goLink(f,!1,()=>{}):(console.warn(`Internal link not found in readingOrder: ${h}`),this.listeners.handleLocator(new m({href:s}).locator))}catch(h){console.warn(`Couldn't resolve internal link for ${s}: ${h}`),this.listeners.handleLocator(new m({href:s}).locator)}}else console.log("Clicked on",a)}else if(e==="click"?this.listeners.click(o):this.listeners.tap(o))break;break;case"scroll":this.listeners.scroll(t);break;case"zoom":this.listeners.zoom(t);break;case"progress":{const a=i&&this.framePool._frameFor(this.currentLocation.href.split("#")[0]);if(i&&i!==a)break;this.syncLocation(t);break}case"content_protection":const n=t;this.listeners.contentProtection(n.type,n);break;case"context_menu":this.listeners.contextMenu(t);break;case"keyboard_peripherals":const l=t,c={...l,interactiveElement:void 0};l.interactiveElement&&(c.interactiveElement=new DOMParser().parseFromString(l.interactiveElement,"text/html").body.children[0]),this.listeners.peripheral(c);break;case"log":console.log(this.framePool.currentFrames[0]?.source?.split("/")[3],...t);break;default:this.listeners.customEvent(e,t);break}}determineModules(){const e=D.slice(),t=E(this.pub.metadata);return t==="cjk-vertical"||t==="mongolian-vertical"?e.map(i=>i==="webpub_snapper"?"cjk_vertical_snapper":i):e}attachListener(){this.framePool.currentFrames.filter(t=>!!t).forEach(t=>{t.msg&&(t.msg.listener=(i,r)=>{this.eventListener(i,r,t)})}),this._reapplyDecorationsToCurrentFrame(),this._watchTextLayoutInCurrentFrame(),this._sendNavigationLock()}async apply(){if(await this.framePool.update(this.pub,this.currentLocation,this.determineModules()),this.attachListener(),this.pub.readingOrder.findIndexWithHref(this.currentLocation.href)<0)throw Error("Link for "+this.currentLocation.href+" not found!")}async destroy(){this._destroyed=!0,this._suspiciousActivityListener&&window.removeEventListener(w,this._suspiciousActivityListener),this._keyboardPeripheralListener&&window.removeEventListener(y,this._keyboardPeripheralListener),this._navigatorProtector?.destroy(),this._keyboardPeripheralsManager?.destroy(),await this.framePool?.destroy(),this._decorations.clear(),this._decorationObservers.clear(),this._decorationHoveredDecorations.clear(),this._decorationActivationState.clear(),this._decorationHoverState.clear(),this._decorationResizeSelectors.clear()}supportsDecorationStyle(e){return z(e,this._decoratorConfig.decorationTemplates)}registerDecorationObserver(e,t){this._decorationObservers.has(e)||this._decorationObservers.set(e,new Set),this._decorationObservers.get(e).add(t),t.onDecorationActivated&&(this._decorationActivationState.set(e,!0),this._sendDecorationActivatable(e,!0)),(t.onDecorationPointerEnter||t.onDecorationPointerLeave)&&(this._decorationHoverState.set(e,!0),this._sendDecorationHoverable(e,!0))}unregisterDecorationObserver(e){this._decorationObservers.forEach((t,i)=>{if(!t.has(e))return;t.delete(e);const r=[...t].some(n=>n.onDecorationActivated);this._decorationActivationState.has(i)&&!r&&(this._decorationActivationState.delete(i),this._sendDecorationActivatable(i,!1));const o=[...t].some(n=>n.onDecorationPointerEnter||n.onDecorationPointerLeave);this._decorationHoverState.has(i)&&!o&&(this._decorationHoverState.delete(i),this._sendDecorationHoverable(i,!1))})}_sendDecorationActivatable(e,t){const i=this.framePool?.currentFrames[0];i?.msg&&i.msg.send("decoration_activatable",{group:e,activatable:t})}_sendDecorationHoverable(e,t){const i=this.framePool?.currentFrames[0];i?.msg&&i.msg.send("decoration_hoverable",{group:e,hoverable:t})}addDecorationResizeTarget(e){this._decorationResizeSelectors.add(e),this.framePool?.addResizeTarget(e)}removeDecorationResizeTarget(e){this._decorationResizeSelectors.delete(e),this.framePool?.removeResizeTarget(e)}applyDecorations(e,t){const i=this._decorations.get(t)??[],r=new Map(i.map(h=>[h.id,h])),o=new Map(e.map(h=>[h.id,h])),n=[],l=[],c=[];for(const[h,f]of r)o.has(h)?V(f,o.get(h))||c.push(o.get(h)):n.push(h);for(const[h,f]of o)r.has(h)||l.push(f);this._decorations.set(t,e),this._sendDecorationOps(t,n,l,c,i);const a=this._decorationActivationState.get(t);a!==void 0&&this._sendDecorationActivatable(t,a);const s=this._decorationHoverState.get(t);s!==void 0&&this._sendDecorationHoverable(t,s)}_sendDecorationOps(e,t,i,r,o){const n=this.framePool?.currentFrames[0];if(!n?.msg)return;const l=this.currentLocation.href,c=new Map(o.map(a=>[a.id,a]));for(const a of t){const s=c.get(a);!s||s.locator.href!==l||n.msg.send("decorate",{group:e,action:"remove",decoration:{id:a}})}for(const a of i)a.locator.href===l&&n.msg.send("decorate",{group:e,action:"add",decoration:_(a,this._decoratorConfig.decorationTemplates)});for(const a of r)a.locator.href===l&&n.msg.send("decorate",{group:e,action:"update",decoration:_(a,this._decoratorConfig.decorationTemplates)})}_reapplyDecorationsToCurrentFrame(){const e=this.framePool?.currentFrames[0];if(!e?.msg)return;const t=this.currentLocation.href;for(const[i,r]of this._decorations){const o=r.filter(n=>n.locator.href===t);if(o.length!==0){e.msg.send("decorate",{group:i,action:"clear"});for(const n of o)e.msg.send("decorate",{group:i,action:"add",decoration:_(n,this._decoratorConfig.decorationTemplates)})}}for(const[i,r]of this._decorationActivationState)e.msg.send("decoration_activatable",{group:i,activatable:r});for(const[i,r]of this._decorationHoverState)e.msg.send("decoration_hoverable",{group:i,hoverable:r})}watchTextLayout(e,t){const i={href:e[0]?.href.split("#")[0]??"",pieces:e.map(r=>[r.text?.serialize(),g(r.locations)]),cb:t};return this._textLayoutWatch=i,this._watchTextLayoutInCurrentFrame(!0),()=>{this._textLayoutWatch===i&&(this._textLayoutWatch=void 0,this._watchTextLayoutInCurrentFrame())}}lockNavigation(e){this._navigationLocked=e,this._sendNavigationLock()}_sendNavigationLock(){this.framePool?.currentFrames[0]?.msg?.send("lock_navigation",this._navigationLocked)}async findPointedPiece(e,t){const i=this.framePool.currentFrames.filter(s=>!!s),r=i.findIndex(s=>s.source===e.targetFrameSrc),o=r>=0?this.viewport.readingOrder[r]:void 0;if(!o||!e.cssSelector)return;const n=t.filter(s=>s.href.split("#")[0]===o);if(n.length===0)return;const l=`${++this._pointedPieceRequestId}`;let c;const a=await new Promise(s=>{this._pointedPieceRequests.set(l,s),c=setTimeout(()=>s(-1),j);const h={id:l,cssSelector:e.cssSelector,x:e.x,y:e.y,pieces:n.map(p=>[p.text?.serialize(),g(p.locations)])};i[r].msg?.send("pointed_piece",h,()=>s(-1))||s(-1)});return clearTimeout(c),this._pointedPieceRequests.delete(l),n[a]}_watchTextLayoutInCurrentFrame(e=!1){const t=this.framePool?.currentFrames[0],i=this._textLayoutWatch,r=i&&t&&this.currentLocation?.href.split("#")[0]===i.href?t:void 0;if(r===this._textLayoutFrame&&!e)return;const o=this._textLayoutFrame;o&&o!==r&&!o.isDestroyed&&o.msg?.send("watch_text_layout",[]),this._textLayoutFrame=r,r&&i&&r.msg?.send("watch_text_layout",i.pieces)}_handleDecorationActivated(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return!1;const i=(this._decorations.get(e.group)??[]).find(n=>n.id===e.decorationId);if(!i)return!1;const r={decoration:i,group:e.group,rect:e.rect,point:e.point};let o=!1;for(const n of t)n.onDecorationActivated?.(r)&&(o=!0);return o}_handleDecorationPointerEnter(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId);if(!i)return;this._decorationHoveredDecorations.set(e.group,i);const r={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerEnter?.(r)}_handleDecorationPointerLeave(e){const t=this._decorationObservers.get(e.group);if(!t||t.size===0)return;const i=(this._decorations.get(e.group)??[]).find(o=>o.id===e.decorationId)??this._decorationHoveredDecorations.get(e.group);if(this._decorationHoveredDecorations.delete(e.group),!i)return;const r={decoration:i,group:e.group,rect:e.rect,point:e.point};for(const o of t)o.onDecorationPointerLeave?.(r)}async changeResource(e){if(e===0)return!1;const t=this.pub.readingOrder.findIndexWithHref(this.currentLocation.href),i=Math.max(0,Math.min(this.pub.readingOrder.items.length-1,t+e));return i===t?!1:(this.currentIndex=i,this.currentLocation=this.createCurrentLocator(),await this.apply(),!0)}updateViewport(e){this.webViewport.readingOrder=[],this.webViewport.progressions.clear(),this.webViewport.positions=null,this.currentLocation&&(this.webViewport.readingOrder.push(this.currentLocation.href),this.webViewport.progressions.set(this.currentLocation.href,e),this.currentLocation.locations?.position!==void 0&&(this.webViewport.positions=[this.currentLocation.locations.position]))}async syncLocation(e){const t=e;this.currentLocation&&(this.currentLocation=this.currentLocation.copyWithLocations({progression:t.start})),this.updateViewport(t),this.listeners.positionChanged(this.currentLocation);const i=t.fragmentId?this.currentLocation.copyWithLocations({fragments:[`#${t.fragmentId}`]}):this.currentLocation;this._visibleFragmentIds=t.visibleFragmentIds??[],this._notifyTimelineChange(i),await this.framePool.update(this.pub,this.currentLocation,this.determineModules())}goBackward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this.changeResource(-1).then(i=>{this._isNavigating=!1,t(i)})}goForward(e,t){if(this._isNavigating){t(!1);return}this._isNavigating=!0,this.changeResource(1).then(i=>{this._isNavigating=!1,t(i)})}get currentLocator(){return this.currentLocation}get viewport(){return this.webViewport}get isScrollStart(){const e=this.viewport.readingOrder[0];return this.viewport.progressions.get(e)?.start===0}get isScrollEnd(){const e=this.viewport.readingOrder[this.viewport.readingOrder.length-1];return this.viewport.progressions.get(e)?.end===1}get canGoBackward(){const e=this.pub.readingOrder.items[0]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.start===0)}get canGoForward(){const e=this.pub.readingOrder.items[this.pub.readingOrder.items.length-1]?.href;return!(this.viewport.progressions.has(e)&&this.viewport.progressions.get(e)?.end===1)}get readingProgression(){return this.pub.metadata.effectiveReadingProgression}get publication(){return this.pub}get timeline(){const e=this.pub.timeline;return this._wrappedTimeline||(this._wrappedTimeline=new Proxy(e,{get:(t,i)=>{if(i!=="navigableFrom"){const r=Reflect.get(t,i,t);return typeof r=="function"?r.bind(t):r}return r=>{const o=this._visibleFragmentIds;let n=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[0]}`]})):void 0)??r;const l=(o.length?t.locate(this.currentLocation.copyWithLocations({fragments:[`#${o[o.length-1]}`]})):void 0)??r;if(this.isScrollStart){const s=t.ancestors(n).find(h=>h.references.includes(this.currentLocation.href));s&&(n=s)}const c=t.navigableFrom(n).previous,a=t.navigableFrom(l).next;return{previous:c,next:a}}}})),this._wrappedTimeline}async loadLocator(e,t){let i=!1,r=g(e.locations);if(e.text?.highlight?i=await new Promise((c,a)=>{this.framePool.currentFrames[0].msg.send("go_text",r?[e.text?.serialize(),r]:e.text?.serialize(),s=>c(s))}):r&&(i=await new Promise((c,a)=>{this.framePool.currentFrames[0].msg.send("go_text",["",r],s=>c(s))})),i){t(i);return}const o=k(e.locations);if(o&&(i=await new Promise((c,a)=>{this.framePool.currentFrames[0].msg.send("go_id",o,s=>c(s))})),i){t(i);return}const n=e?.locations?.progression;n&&n>0?i=await new Promise((c,a)=>{this.framePool.currentFrames[0].msg.send("go_progression",n,s=>c(s))}):i=!0,t(i)}completeLocator(e){if(!e.href){const t=this.pub.readingOrder.items;let i=!1;if(typeof e.locations.position=="number"){const r=t[e.locations.position-1];r&&(e=(this.pub.manifest.locatorFromLink(r)||new u({href:r.href,type:r.type||"text/html"})).copyWithLocations(e.locations),i=!0)}if(!i&&typeof e.locations?.totalProgression=="number"){const r=e.locations.totalProgression,o=Math.min(t.length-1,Math.max(0,Math.round(r*(t.length-1)))),n=t[o];n&&(e=(this.pub.manifest.locatorFromLink(n)||new u({href:n.href,type:n.type||"text/html"})).copyWithLocations(e.locations))}}return e}go(e,t,i){e=this.completeLocator(e);const r=e.href.split("#")[0];if(!this.pub.readingOrder.findWithHref(r))return i(this.listeners.handleLocator(e));const n=this.pub.readingOrder.findIndexWithHref(r);if(n>=0&&(this.currentIndex=n),this._isNavigating){i(!1);return}this._isNavigating=!0,this.currentLocation=this.createCurrentLocator(),this.apply().then(()=>this.loadLocator(e,l=>{this._isNavigating=!1,i(l)})).then(()=>{this.attachListener()})}goLink(e,t,i){return this.go(e.locator,t,i)}createCurrentLocator(){const t=this.pub.readingOrder.items[this.currentIndex];if(!t)throw new Error("No current resource available");const r=this.currentLocation&&this.currentLocation.href===t.href&&this.currentLocation.locations.progression?this.currentLocation.locations.progression:0;return this.pub.manifest.locatorFromLink(t)||new u({href:t.href,type:t.type||"text/html",locations:new S({fragments:[],progression:r,position:this.currentIndex+1})})}_notifyTimelineChange(e){const t=this.timeline.locate(e),i=!B(this._visibleFragmentIds,this._notifiedVisibleFragmentIds);(t!==this._currentTimelineItem||i)&&(this._currentTimelineItem=t,this._notifiedVisibleFragmentIds=this._visibleFragmentIds,this.listeners.timelineItemChanged(t))}}const le=q;export{le as ExperimentalWebPubNavigator,q as WebPubNavigator};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@readium/navigator",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Next generation SDK for publications in Web Apps",
|
|
6
6
|
"author": "readium",
|
|
@@ -41,13 +41,15 @@
|
|
|
41
41
|
"types"
|
|
42
42
|
],
|
|
43
43
|
"engines": {
|
|
44
|
-
"node": ">=
|
|
44
|
+
"node": ">=24"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@readium/
|
|
48
|
-
"@readium/
|
|
49
|
-
"@readium/
|
|
50
|
-
"@readium/
|
|
47
|
+
"@readium/speech": "^0.14.1",
|
|
48
|
+
"@readium/decorator": "1.3.0",
|
|
49
|
+
"@readium/guided-navigation": "1.1.1",
|
|
50
|
+
"@readium/helpers": "1.2.1",
|
|
51
|
+
"@readium/shared": "2.8.0",
|
|
52
|
+
"@readium/navigator-html-injectables": "2.9.0"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
55
|
"@readium/css": "^2.0.5",
|