@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.
Files changed (52) hide show
  1. package/dist/divina/DivinaNavigator.js +1 -1
  2. package/dist/epub/EpubNavigator.js +1 -1
  3. package/dist/epub/frame/FramePoolManager.js +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/preferences/guards.js +1 -1
  6. package/dist/readaloud/GuidedNavigationProvider.js +1 -0
  7. package/dist/readaloud/ReadAloudNavigator.js +1 -0
  8. package/dist/readaloud/ReadingUnit.js +1 -0
  9. package/dist/readaloud/SpeechProgress.js +1 -0
  10. package/dist/readaloud/preferences/ReadAloudDefaults.js +1 -0
  11. package/dist/readaloud/preferences/ReadAloudPreferences.js +1 -0
  12. package/dist/readaloud/preferences/ReadAloudPreferencesEditor.js +1 -0
  13. package/dist/readaloud/preferences/ReadAloudSettings.js +1 -0
  14. package/dist/webpub/WebPubFrameManager.js +1 -1
  15. package/dist/webpub/WebPubFramePoolManager.js +1 -1
  16. package/dist/webpub/WebPubNavigator.js +1 -1
  17. package/package.json +8 -6
  18. package/src/divina/DivinaNavigator.ts +1 -0
  19. package/src/epub/EpubNavigator.ts +127 -21
  20. package/src/epub/frame/FramePoolManager.ts +5 -0
  21. package/src/index.ts +1 -0
  22. package/src/preferences/guards.ts +11 -0
  23. package/src/readaloud/GuidedNavigationProvider.ts +87 -0
  24. package/src/readaloud/ReadAloudNavigator.ts +949 -0
  25. package/src/readaloud/ReadingUnit.ts +154 -0
  26. package/src/readaloud/SpeechProgress.ts +60 -0
  27. package/src/readaloud/index.ts +17 -0
  28. package/src/readaloud/preferences/ReadAloudDefaults.ts +24 -0
  29. package/src/readaloud/preferences/ReadAloudPreferences.ts +104 -0
  30. package/src/readaloud/preferences/ReadAloudPreferencesEditor.ts +115 -0
  31. package/src/readaloud/preferences/ReadAloudSettings.ts +44 -0
  32. package/src/readaloud/preferences/index.ts +4 -0
  33. package/src/webpub/WebPubFrameManager.ts +4 -0
  34. package/src/webpub/WebPubFramePoolManager.ts +5 -0
  35. package/src/webpub/WebPubNavigator.ts +114 -10
  36. package/types/src/epub/EpubNavigator.d.ts +26 -1
  37. package/types/src/epub/frame/FramePoolManager.d.ts +2 -0
  38. package/types/src/index.d.ts +1 -0
  39. package/types/src/preferences/guards.d.ts +1 -0
  40. package/types/src/readaloud/GuidedNavigationProvider.d.ts +28 -0
  41. package/types/src/readaloud/ReadAloudNavigator.d.ts +158 -0
  42. package/types/src/readaloud/ReadingUnit.d.ts +58 -0
  43. package/types/src/readaloud/SpeechProgress.d.ts +19 -0
  44. package/types/src/readaloud/index.d.ts +6 -0
  45. package/types/src/readaloud/preferences/ReadAloudDefaults.d.ts +11 -0
  46. package/types/src/readaloud/preferences/ReadAloudPreferences.d.ts +58 -0
  47. package/types/src/readaloud/preferences/ReadAloudPreferencesEditor.d.ts +37 -0
  48. package/types/src/readaloud/preferences/ReadAloudSettings.d.ts +26 -0
  49. package/types/src/readaloud/preferences/index.d.ts +4 -0
  50. package/types/src/webpub/WebPubFrameManager.d.ts +1 -0
  51. package/types/src/webpub/WebPubFramePoolManager.d.ts +2 -0
  52. 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 i,DecorationLayout as p,DecorationStyleType as f,DecorationWidth as g,decorationsEqual as m,resolveDecorationForWire as x,supportsDecorationStyle as s}from"@readium/decorator";import{ExperimentalWebPubNavigator as l,WebPubNavigator as P}from"./webpub/WebPubNavigator.js";import{WebPubBlobBuilder as d}from"./webpub/WebPubBlobBuilder.js";import{WebPubFrameManager as S}from"./webpub/WebPubFrameManager.js";import{WebPubFramePoolManager as D}from"./webpub/WebPubFramePoolManager.js";import{WebPubDefaults as R}from"./webpub/preferences/WebPubDefaults.js";import{WebPubPreferencesEditor as W}from"./webpub/preferences/WebPubPreferencesEditor.js";import{WebPubPreferences as F}from"./webpub/preferences/WebPubPreferences.js";import{WebPubSettings as L}from"./webpub/preferences/WebPubSettings.js";import{WebRSProperties as T,WebUserProperties as I}from"./webpub/css/Properties.js";import{WebPubCSS as O}from"./webpub/css/WebPubCSS.js";import{EpubNavigator as B}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 q}from"./epub/frame/FramePoolManager.js";import{FXLCoordinator as U,HorizontalThird as w,VerticalThird as G}from"./epub/fxl/FXLCoordinator.js";import{FXLFrameManager as Q}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 ne}from"./epub/preferences/EpubDefaults.js";import{EpubPreferencesEditor as pe}from"./epub/preferences/EpubPreferencesEditor.js";import{EpubPreferences as ge}from"./epub/preferences/EpubPreferences.js";import{EpubSettings as xe}from"./epub/preferences/EpubSettings.js";import{RSProperties as ue,UserProperties as le}from"./epub/css/Properties.js";import{ReadiumCSS as be}from"./epub/css/ReadiumCSS.js";import{DivinaNavigator as ce}from"./divina/DivinaNavigator.js";import{DivinaPage as ve,DivinaSpreader as De}from"./divina/DivinaSpreader.js";import{DivinaPageManager as Re,placeholderSVG as Ce}from"./divina/DivinaPageManager.js";import{DivinaPagedPresenter as he}from"./divina/DivinaPagedPresenter.js";import{DivinaScrolledPresenter as Me}from"./divina/DivinaScrolledPresenter.js";import{DivinaPeripherals as Ne}from"./divina/DivinaPeripherals.js";import{DivinaQuality as Ie,MOBILE_MAX_HEIGHT as Ae,MOBILE_MAX_WIDTH as Oe,gatherVariants as ye,selectVariant as Be}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 ze}from"./divina/preferences/DivinaPreferencesEditor.js";import{DivinaSettings as we}from"./divina/preferences/DivinaSettings.js";import{WebAudioEngine as je}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 nr}from"./helpers/lineLength.js";import{getScriptMode as pr}from"./helpers/scriptMode.js";import{BooleanPreference as gr,EnumPreference as mr,Preference as xr,RangePreference as sr}from"./preferences/Preference.js";import{TextAlignment as lr,experiments as Pr,filterRangeConfig as br,fontSizeRangeConfig as dr,fontWeightRangeConfig as cr,fontWidthRangeConfig as Sr,i18n as vr,letterSpacingRangeConfig as Dr,lineHeightRangeConfig as Er,lineLengthRangeConfig as Rr,paragraphIndentRangeConfig as Cr,paragraphSpacingRangeConfig as Wr,playbackRateRangeConfig as hr,settings as Fr,skipIntervalRangeConfig as Mr,volumeRangeConfig as Lr,wordSpacingRangeConfig as Nr,zoomRangeConfig as Tr}from"./preferences/Types.js";import{ensureBoolean as Ar,ensureEnumValue as Or,ensureExperiment as yr,ensureFilter as Br,ensureLessThanOrEqual as Vr,ensureMoreThanOrEqual as Xr,ensureNonNegative as _r,ensureString as Hr,ensureValueInRange as kr,withFallback as qr}from"./preferences/guards.js";import{Properties as Ur}from"./css/Properties.js";import{Injector as Gr}from"./injection/Injector.js";export{Ke as AudioDefaults,tr as AudioNavigator,Ye as AudioPreferences,rr as AudioPreferencesEditor,$e as AudioSettings,i as BUILTIN_DECORATION_TYPES,gr as BooleanPreference,p as DecorationLayout,f as DecorationStyleType,g as DecorationWidth,Xe as DivinaDefaults,ce as DivinaNavigator,ve as DivinaPage,Re as DivinaPageManager,he as DivinaPagedPresenter,Ne as DivinaPeripherals,He as DivinaPreferences,ze as DivinaPreferencesEditor,Ie as DivinaQuality,Me as DivinaScrolledPresenter,we as DivinaSettings,De as DivinaSpreader,mr as EnumPreference,ne as EpubDefaults,B as EpubNavigator,ge as EpubPreferences,pe as EpubPreferencesEditor,xe as EpubSettings,l as ExperimentalWebPubNavigator,U as FXLCoordinator,Q as FXLFrameManager,J as FXLFramePoolManager,Z as FXLPeripherals,re as FXLSpreader,X as FrameComms,H as FrameManager,q as FramePoolManager,w as HorizontalThird,Gr as Injector,nr as LineLengths,Ae as MOBILE_MAX_HEIGHT,Oe as MOBILE_MAX_WIDTH,o as MediaNavigator,t as Navigator,oe as Orientation,xr as Preference,Ur as Properties,ue as RSProperties,sr as RangePreference,be as ReadiumCSS,te as Spread,lr as TextAlignment,le as UserProperties,G as VerticalThird,a as VisualNavigator,je as WebAudioEngine,d as WebPubBlobBuilder,O as WebPubCSS,R as WebPubDefaults,S as WebPubFrameManager,D as WebPubFramePoolManager,P as WebPubNavigator,F as WebPubPreferences,W as WebPubPreferencesEditor,L as WebPubSettings,T as WebRSProperties,I as WebUserProperties,m as decorationsEqual,Ar as ensureBoolean,Or as ensureEnumValue,yr as ensureExperiment,Br as ensureFilter,Vr as ensureLessThanOrEqual,Xr as ensureMoreThanOrEqual,_r as ensureNonNegative,Hr as ensureString,kr as ensureValueInRange,Pr as experiments,br as filterRangeConfig,dr as fontSizeRangeConfig,cr as fontWeightRangeConfig,Sr as fontWidthRangeConfig,ye as gatherVariants,pr as getScriptMode,vr as i18n,$ as isTypedOMSupported,Dr as letterSpacingRangeConfig,Er as lineHeightRangeConfig,Rr as lineLengthRangeConfig,Cr as paragraphIndentRangeConfig,Wr as paragraphSpacingRangeConfig,Ce as placeholderSVG,hr as playbackRateRangeConfig,x as resolveDecorationForWire,Be as selectVariant,Fr as settings,Mr as skipIntervalRangeConfig,ke as stripWidthRangeConfig,s as supportsDecorationStyle,Lr as volumeRangeConfig,qr as withFallback,Nr as wordSpacingRangeConfig,Tr as zoomRangeConfig};
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 e(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 l(n){return typeof n=="boolean"||n==null?n:void 0}function s(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 h(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 m(n,r){return n===void 0?r:n}function y(n){if(n!==void 0)return n===null?null:n.filter(r=>r in o)}export{l as ensureBoolean,s as ensureEnumValue,y as ensureExperiment,c as ensureFilter,e as ensureLessThanOrEqual,f as ensureMoreThanOrEqual,h as ensureNonNegative,d as ensureString,b as ensureValueInRange,m as withFallback};
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 w{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 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{w as WebPubFrameManager};
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.11.1",
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": ">=18"
44
+ "node": ">=24"
45
45
  },
46
46
  "dependencies": {
47
- "@readium/decorator": "1.2.4",
48
- "@readium/helpers": "1.1.1",
49
- "@readium/navigator-html-injectables": "2.8.4",
50
- "@readium/shared": "2.6.0"
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",