@readium/shared 2.3.2 → 2.4.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.
@@ -1 +1 @@
1
- import{getTime as g,getHtmlId as v}from"../../html/Locations.js";import{Profile as p}from"../../Profiles.js";import{isNptStartOfResource as k,formatNptTime as I,parseNptTime as T}from"../../../util/npt.js";class l{constructor(i,t,e=[],s=[],n=void 0){this._trimmedLinkMap=new Map,this._allItems=i,this.linkMap=t,this._conformsTo=e,this.tocLinks=s,this._tocDepth=n}static build(i,t={}){const e=i.toc?.items??[],s=i.readingOrder.items,{depth:n}=t,o=i.metadata?.conformsTo??[],r=new Map,c=[];for(let h=0;h<s.length;h++){const f=s[h],a=l.bareHref(f.href),d=f.title??l.findTitleInToc(e,a,n),u=l.collectChildrenFromToc(e,a,n,1,r),m={title:d,references:[f.href],children:u.length>0?u:void 0};r.set(m,f),c.push(m)}return new l(c,r,o,e,n)}augment(i){for(const t of this.flatAll){const e=this.linkFor(t);if(!e)continue;const s=i(t,e);s.position!==void 0&&(t.position=s.position),s.scroll!==void 0&&(t.scroll=s.scroll),s.role!==void 0&&(t.role=s.role)}}get depth(){return this._depth}set depth(i){this._depth!==i&&(this._depth=i,this._tocDepth=i,this._items=void 0,this._flat=void 0,this._toc=void 0)}get items(){return this._items||(this._depth!==void 0?(this._trimmedLinkMap=new Map,this._items=l.trimToDepth(this._allItems,this._depth,this.linkMap,this._trimmedLinkMap)):this._items=this._allItems),this._items}locate(i){const t=i.href.split("#")[0],e=g(i.locations),s=v(i.locations),n=i.locations.progression;if(e!==void 0){let o=-1/0,r;for(const c of this.flat){if(!this.itemMatchesHref(c,t))continue;const h=this.itemStartTime(c,t);h!==void 0&&h<=e&&h>o&&(o=h,r=c)}if(r)return r}if(s){const o=this.flat.find(r=>this.itemMatchesHref(r,t)?r.references.some(c=>c.split("#")[1]===s):!1);if(o)return o}if(n!==void 0){let o=-1/0,r;for(const h of this.flat){if(!this.itemMatchesHref(h,t))continue;const f=this.itemScrollPosition(h);f!==void 0&&f<=n&&f>o&&(o=f,r=h)}if(r)return r;const c=this.items.find(h=>this.itemMatchesHref(h,t));if(c?.children?.length&&!c.children.some(h=>h.scroll!==void 0)){const h=Math.min(Math.floor(n*c.children.length),c.children.length-1);return c.children[h]}}return this.flat.find(o=>this.itemMatchesHref(o,t))}adjacentTo(i){const t=this.flat.indexOf(i);return{previous:t>0?this.flat[t-1]:void 0,next:t>=0&&t<this.flat.length-1?this.flat[t+1]:void 0}}segmentsForHref(i){const t=i.split("#")[0],e=this.items.find(s=>this.itemMatchesHref(s,t));return e?e.children?.length?e.children:[e]:[]}ancestors(i){return this.ancestorPath(this.items,i)??[]}linkFor(i){return this.linkMap.get(i)??this._trimmedLinkMap.get(i)}get contextualizedToc(){return this._toc||(this._toc=this.tocLinks.length>0?this.buildTocEntries(this.tocLinks,this._tocDepth,1):this._allItems.map(i=>this.entryFor(this.linkFor(i),i))),this._toc}tocEntryFor(i){const t=this.linkFor(i);if(!t)return;const e=this.findTocEntryByLink(this.contextualizedToc,t);if(e)return e;const s=this.nearestTocEntryForResource(t.href,i);return s||this.previousResolvedTocEntry(t)}get flat(){return this._flat||(this._flat=this.flattenItems(this.items)),this._flat}get flatAll(){return this.flattenItems(this._allItems)}static findTitleInToc(i,t,e){const{atStart:s,fragments:n}=l.collectTocCandidates(i,t,e,1);if(s.length>0)return s[0].title;if(n.length===1)return n[0].title}static collectChildrenFromToc(i,t,e,s,n){if(e!==void 0&&s>e)return[];const o=[];for(const r of i){const c=l.bareHref(r.href),h=r.href.startsWith("#");if((c===t||h&&c==="")&&r.title&&!l.isStartOfResource(r.href)){const a=c===""?t+r.href:r.href,d={title:r.title,references:[a]};n.set(d,r),o.push(d)}r.children?.items?.length&&o.push(...l.collectChildrenFromToc(r.children.items,t,e,s+1,n))}return o}static collectTocCandidates(i,t,e,s){if(e!==void 0&&s>e)return{atStart:[],fragments:[]};const n=[],o=[];for(const r of i){const c=l.bareHref(r.href),h=r.href.startsWith("#");if((c===t||h&&c==="")&&r.title&&(l.isStartOfResource(r.href)?n.push(r):o.push(r)),r.children?.items?.length){const f=l.collectTocCandidates(r.children.items,t,e,s+1);n.push(...f.atStart),o.push(...f.fragments)}}return{atStart:n,fragments:o}}static isStartOfResource(i){const t=i.split("#")[1];if(!t)return!0;const e=t.match(/(?:^|&)t=([^&]+)/);return e!==null&&k(e[1])}get linkToItem(){if(!this._linkToItem){this._linkToItem=new Map;for(const[i,t]of this.linkMap)this._linkToItem.set(t,i)}return this._linkToItem}buildTocEntries(i,t,e){return t!==void 0&&e>t?[]:i.map(s=>{const n=this.linkToItem.get(s)??this.resourceStartItem(s.href),o=s.children?.items?.length?this.buildTocEntries(s.children.items,t,e+1):[];return{...this.entryFor(s,n),children:o.length>0?o:void 0}})}tocLinksFlat(i,t,e){if(t!==void 0&&e>t)return[];const s=[];for(const n of i)s.push(n),n.children?.items?.length&&s.push(...this.tocLinksFlat(n.children.items,t,e+1));return s}entryFor(i,t){const e=this._conformsTo.includes(p.AUDIOBOOK);return{link:i,position:!e&&t?.position!==void 0?String(t.position):void 0,timestamp:e&&t?.position!==void 0?I(t.position):void 0}}resourceStartItem(i){const t=l.bareHref(i);return this._allItems.find(e=>this.itemMatchesHref(e,t))}findTocEntryByLink(i,t){for(const e of i){if(e.link===t)return e;if(e.children){const s=this.findTocEntryByLink(e.children,t);if(s)return s}}}nearestTocEntryForResource(i,t){const e=l.bareHref(i),s=this.tocLinksFlat(this.tocLinks,this._tocDepth,1).filter(f=>l.bareHref(f.href)===e).map(f=>({link:f,item:this.linkToItem.get(f)??this.resourceStartItem(f.href)}));if(s.length===0)return;const n=this._conformsTo.includes(p.AUDIOBOOK),o=n?t.position??0:t.scroll??0;let r,c=-1/0;for(const f of s){const a=n?f.item?.position??0:f.item?.scroll??0;a<=o&&a>c&&(c=a,r=f)}const h=r??s[0];return this.findTocEntryByLink(this.contextualizedToc,h.link)}previousResolvedTocEntry(i){const t=this._allItems.findIndex(e=>this.linkFor(e)===i);if(t!==-1)for(let e=t-1;e>=0;e--){const s=this.linkFor(this._allItems[e]);if(!s)continue;const n=l.bareHref(s.href),{atStart:o,fragments:r}=l.collectTocCandidates(this.tocLinks,n,this._tocDepth,1),c=o.filter(d=>l.bareHref(d.href)===n),h=r.filter(d=>l.bareHref(d.href)===n),f=c[0]??(h.length>0?h[h.length-1]:void 0);if(!f)continue;const a=this.findTocEntryByLink(this.contextualizedToc,f);if(a)return a}}static trimToDepth(i,t,e,s){return i.map(n=>{const o={...n,children:t>1&&n.children?.length?l.trimToDepth(n.children,t-1,e,s):void 0},r=e.get(n);return r&&s.set(o,r),o})}flattenItems(i){const t=[];for(const e of i)t.push(e),e.children&&t.push(...this.flattenItems(e.children));return t}itemStartTime(i,t){for(const e of i.references){const s=e.indexOf("#"),n=s>=0?e.slice(0,s):e,o=s>=0?e.slice(s+1):void 0;if((n||t)!==t)continue;if(!o)return;const c=o.match(/(?:^|&)t=([^&]+)/);return c?T(c[1]):void 0}}itemMatchesHref(i,t){return i.references.some(e=>{const s=e.split("#")[0];return s===t||s===""})}ancestorPath(i,t){for(const e of i){if(e===t)return[];if(e.children){const s=this.ancestorPath(e.children,t);if(s!==null)return[e,...s]}}return null}itemScrollPosition(i){return i.scroll}static bareHref(i){return i.split("#")[0]}}export{l as Timeline};
1
+ import{getTime as g,getHtmlId as v}from"../../html/Locations.js";import{Profile as p}from"../../Profiles.js";import{isNptStartOfResource as k,formatNptTime as I,parseNptTime as T}from"../../../util/npt.js";class l{constructor(i,t,e=[],s=[],n=void 0){this._trimmedLinkMap=new Map,this._allItems=i,this.linkMap=t,this._conformsTo=e,this.tocLinks=s,this._tocDepth=n}static build(i,t={}){const e=i.toc?.items??[],s=i.readingOrder.items,{depth:n}=t,o=i.metadata?.conformsTo??[],r=new Map,c=[];for(let h=0;h<s.length;h++){const f=s[h],a=l.bareHref(f.href),d=f.title??l.findTitleInToc(e,a,n),u=l.collectChildrenFromToc(e,a,n,1,r),m={title:d,references:[f.href],children:u.length>0?u:void 0};r.set(m,f),c.push(m)}return new l(c,r,o,e,n)}augment(i){for(const t of this.flatAll){const e=this.linkFor(t);if(!e)continue;const s=i(t,e);s.position!==void 0&&(t.position=s.position),s.scroll!==void 0&&(t.scroll=s.scroll),s.role!==void 0&&(t.role=s.role)}}get depth(){return this._depth}set depth(i){this._depth!==i&&(this._depth=i,this._tocDepth=i,this._items=void 0,this._flat=void 0,this._toc=void 0)}get items(){return this._items||(this._depth!==void 0?(this._trimmedLinkMap=new Map,this._items=l.trimToDepth(this._allItems,this._depth,this.linkMap,this._trimmedLinkMap)):this._items=this._allItems),this._items}locate(i){const t=i.href.split("#")[0],e=g(i.locations),s=v(i.locations),n=i.locations.progression;if(e!==void 0){let o=-1/0,r;for(const c of this.flat){if(!this.itemMatchesHref(c,t))continue;const h=this.itemStartTime(c,t);h!==void 0&&h<=e&&h>o&&(o=h,r=c)}if(r)return r}if(s){const o=this.flat.find(r=>this.itemMatchesHref(r,t)?r.references.some(c=>c.split("#")[1]===s):!1);if(o)return o}if(n!==void 0){let o=-1/0,r;for(const h of this.flat){if(!this.itemMatchesHref(h,t))continue;const f=this.itemScrollPosition(h);f!==void 0&&f<=n&&f>o&&(o=f,r=h)}if(r)return r;const c=this.items.find(h=>this.itemMatchesHref(h,t));if(c?.children?.length&&!c.children.some(h=>h.scroll!==void 0)){const h=Math.min(Math.floor(n*c.children.length),c.children.length-1);return c.children[h]}}return this.flat.find(o=>this.itemMatchesHref(o,t))}navigableFrom(i){const t=this.flat.indexOf(i);return{previous:t>0?this.flat[t-1]:void 0,next:t>=0&&t<this.flat.length-1?this.flat[t+1]:void 0}}segmentsForHref(i){const t=i.split("#")[0],e=this.items.find(s=>this.itemMatchesHref(s,t));return e?e.children?.length?e.children:[e]:[]}ancestors(i){return this.ancestorPath(this.items,i)??[]}linkFor(i){return this.linkMap.get(i)??this._trimmedLinkMap.get(i)}get contextualizedToc(){return this._toc||(this._toc=this.tocLinks.length>0?this.buildTocEntries(this.tocLinks,this._tocDepth,1):this._allItems.map(i=>this.entryFor(this.linkFor(i),i))),this._toc}tocEntryFor(i){const t=this.linkFor(i);if(!t)return;const e=this.findTocEntryByLink(this.contextualizedToc,t);if(e)return e;const s=this.nearestTocEntryForResource(t.href,i);return s||this.previousResolvedTocEntry(t)}get flat(){return this._flat||(this._flat=this.flattenItems(this.items)),this._flat}get flatAll(){return this.flattenItems(this._allItems)}static findTitleInToc(i,t,e){const{atStart:s,fragments:n}=l.collectTocCandidates(i,t,e,1);if(s.length>0)return s[0].title;if(n.length===1)return n[0].title}static collectChildrenFromToc(i,t,e,s,n){if(e!==void 0&&s>e)return[];const o=[];for(const r of i){const c=l.bareHref(r.href),h=r.href.startsWith("#");if((c===t||h&&c==="")&&r.title&&!l.isStartOfResource(r.href)){const a=c===""?t+r.href:r.href,d={title:r.title,references:[a]};n.set(d,r),o.push(d)}r.children?.items?.length&&o.push(...l.collectChildrenFromToc(r.children.items,t,e,s+1,n))}return o}static collectTocCandidates(i,t,e,s){if(e!==void 0&&s>e)return{atStart:[],fragments:[]};const n=[],o=[];for(const r of i){const c=l.bareHref(r.href),h=r.href.startsWith("#");if((c===t||h&&c==="")&&r.title&&(l.isStartOfResource(r.href)?n.push(r):o.push(r)),r.children?.items?.length){const f=l.collectTocCandidates(r.children.items,t,e,s+1);n.push(...f.atStart),o.push(...f.fragments)}}return{atStart:n,fragments:o}}static isStartOfResource(i){const t=i.split("#")[1];if(!t)return!0;const e=t.match(/(?:^|&)t=([^&]+)/);return e!==null&&k(e[1])}get linkToItem(){if(!this._linkToItem){this._linkToItem=new Map;for(const[i,t]of this.linkMap)this._linkToItem.set(t,i)}return this._linkToItem}buildTocEntries(i,t,e){return t!==void 0&&e>t?[]:i.map(s=>{const n=this.linkToItem.get(s)??this.resourceStartItem(s.href),o=s.children?.items?.length?this.buildTocEntries(s.children.items,t,e+1):[];return{...this.entryFor(s,n),children:o.length>0?o:void 0}})}tocLinksFlat(i,t,e){if(t!==void 0&&e>t)return[];const s=[];for(const n of i)s.push(n),n.children?.items?.length&&s.push(...this.tocLinksFlat(n.children.items,t,e+1));return s}entryFor(i,t){const e=this._conformsTo.includes(p.AUDIOBOOK);return{link:i,position:!e&&t?.position!==void 0?String(t.position):void 0,timestamp:e&&t?.position!==void 0?I(t.position):void 0}}resourceStartItem(i){const t=l.bareHref(i);return this._allItems.find(e=>this.itemMatchesHref(e,t))}findTocEntryByLink(i,t){for(const e of i){if(e.link===t)return e;if(e.children){const s=this.findTocEntryByLink(e.children,t);if(s)return s}}}nearestTocEntryForResource(i,t){const e=l.bareHref(i),s=this.tocLinksFlat(this.tocLinks,this._tocDepth,1).filter(f=>l.bareHref(f.href)===e).map(f=>({link:f,item:this.linkToItem.get(f)??this.resourceStartItem(f.href)}));if(s.length===0)return;const n=this._conformsTo.includes(p.AUDIOBOOK),o=n?t.position??0:t.scroll??0;let r,c=-1/0;for(const f of s){const a=n?f.item?.position??0:f.item?.scroll??0;a<=o&&a>c&&(c=a,r=f)}const h=r??s[0];return this.findTocEntryByLink(this.contextualizedToc,h.link)}previousResolvedTocEntry(i){const t=this._allItems.findIndex(e=>this.linkFor(e)===i);if(t!==-1)for(let e=t-1;e>=0;e--){const s=this.linkFor(this._allItems[e]);if(!s)continue;const n=l.bareHref(s.href),{atStart:o,fragments:r}=l.collectTocCandidates(this.tocLinks,n,this._tocDepth,1),c=o.filter(d=>l.bareHref(d.href)===n),h=r.filter(d=>l.bareHref(d.href)===n),f=c[0]??(h.length>0?h[h.length-1]:void 0);if(!f)continue;const a=this.findTocEntryByLink(this.contextualizedToc,f);if(a)return a}}static trimToDepth(i,t,e,s){return i.map(n=>{const o={...n,children:t>1&&n.children?.length?l.trimToDepth(n.children,t-1,e,s):void 0},r=e.get(n);return r&&s.set(o,r),o})}flattenItems(i){const t=[];for(const e of i)t.push(e),e.children&&t.push(...this.flattenItems(e.children));return t}itemStartTime(i,t){for(const e of i.references){const s=e.indexOf("#"),n=s>=0?e.slice(0,s):e,o=s>=0?e.slice(s+1):void 0;if((n||t)!==t)continue;if(!o)return;const c=o.match(/(?:^|&)t=([^&]+)/);return c?T(c[1]):void 0}}itemMatchesHref(i,t){return i.references.some(e=>{const s=e.split("#")[0];return s===t||s===""})}ancestorPath(i,t){for(const e of i){if(e===t)return[];if(e.children){const s=this.ancestorPath(e.children,t);if(s!==null)return[e,...s]}}return null}itemScrollPosition(i){return i.scroll}static bareHref(i){return i.split("#")[0]}}export{l as Timeline};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@readium/shared",
3
- "version": "2.3.2",
3
+ "version": "2.4.0",
4
4
  "type": "module",
5
5
  "description": "Shared models to be used across other Readium projects and implementations in Typescript",
6
6
  "author": "readium",
@@ -228,7 +228,8 @@ export class Timeline {
228
228
  return this.flat.find(item => this.itemMatchesHref(item, href));
229
229
  }
230
230
 
231
- adjacentTo(item: TimelineItem): { previous: TimelineItem | undefined; next: TimelineItem | undefined } {
231
+ /** The items navigable to/from `item`: its previous/next neighbors in the flattened timeline. */
232
+ navigableFrom(item: TimelineItem): { previous: TimelineItem | undefined; next: TimelineItem | undefined } {
232
233
  const index = this.flat.indexOf(item);
233
234
  return {
234
235
  previous: index > 0 ? this.flat[index - 1] : undefined,
@@ -88,7 +88,8 @@ export declare class Timeline {
88
88
  /** Top-level timeline items. Cached; invalidated when `depth` changes. */
89
89
  get items(): TimelineItem[];
90
90
  locate(locator: Locator): TimelineItem | undefined;
91
- adjacentTo(item: TimelineItem): {
91
+ /** The items navigable to/from `item`: its previous/next neighbors in the flattened timeline. */
92
+ navigableFrom(item: TimelineItem): {
92
93
  previous: TimelineItem | undefined;
93
94
  next: TimelineItem | undefined;
94
95
  };