@readium/shared 2.5.1 → 2.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fetcher/HttpFetcher.js +1 -1
- package/dist/fetcher/Resource.js +1 -1
- package/dist/index.js +1 -1
- package/dist/publication/GuidedNavigation.js +1 -1
- package/dist/publication/Manifest.js +1 -1
- package/dist/publication/html/Locations.js +1 -1
- package/dist/util/mediatype/MediaType.js +1 -1
- package/package.json +3 -3
- package/src/fetcher/HttpFetcher.ts +5 -5
- package/src/fetcher/Resource.ts +10 -5
- package/src/publication/GuidedNavigation.ts +120 -45
- package/src/publication/Locator.ts +1 -1
- package/src/publication/Manifest.ts +24 -19
- package/src/publication/html/Locations.ts +3 -7
- package/src/publication/services/content/ContentTokenizer.ts +5 -1
- package/src/publication/services/content/iterators/HTMLResourceContentIterator.ts +2 -0
- package/src/util/mediatype/MediaType.ts +7 -0
- package/src/util/tokenizer/TextTokenizer.ts +17 -4
- package/src/util/tokenizer/Tokenizer.ts +1 -0
- package/types/src/fetcher/HttpFetcher.d.ts +3 -3
- package/types/src/fetcher/Resource.d.ts +6 -2
- package/types/src/publication/GuidedNavigation.d.ts +49 -20
- package/types/src/publication/Locator.d.ts +1 -1
- package/types/src/publication/Manifest.d.ts +4 -0
- package/types/src/publication/services/content/ContentTokenizer.d.ts +5 -0
- package/types/src/publication/services/content/iterators/HTMLResourceContentIterator.d.ts +2 -0
- package/types/src/util/mediatype/MediaType.d.ts +4 -0
- package/types/src/util/tokenizer/TextTokenizer.d.ts +17 -0
- package/types/src/util/tokenizer/Tokenizer.d.ts +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
class n{constructor(t,
|
|
1
|
+
class n{constructor(t,e){this.client=t||window.fetch.bind(window),this.baseUrl=e}links(){return[]}get(t){const e=t.toURL(this.baseUrl);if(e===void 0)throw Error(`Invalid HREF: ${t.href}`);return new i(this.client,t,e)}close(){}}class i{constructor(t,e,r){this.client=t||window.fetch.bind(window),this._link=e,this.url=r}async headResponse(){if(this._headResponse)return this._headResponse;const t=await this.client(this.url,{method:"HEAD"});if(!t.ok)throw new Error(`http HEAD request for ${this.url} failed with HTTP status code ${t.status}`);return this._headResponse=t,t}close(){}async link(){return this._link}async read(t,e){if(t)throw new Error("http read range not implemented!");const r=await this.client(this.url,e?.signal?{signal:e.signal}:void 0);if(!r.ok)throw new Error(`http GET request for ${this.url} failed with HTTP status code ${r.status}`);return new Uint8Array(await r.arrayBuffer())}async length(){const e=(await this.headResponse()).headers.get("content-length");if(e===null||e==="")throw new Error("length for resource unavailable");return parseInt(e)}async readAsJSON(){const t=await this.client(this.url);if(!t.ok)throw new Error(`http GET request for ${this.url} failed with HTTP status code ${t.status}`);return await t.json()}async readAsString(){const t=await this.client(this.url);if(!t.ok)throw new Error(`http GET request for ${this.url} failed with HTTP status code ${t.status}`);return await t.text()}async readAsXML(){const t=await this.client(this.url);if(!t.ok)throw new Error(`http GET request for ${this.url} failed with HTTP status code ${t.status}`);return new DOMParser().parseFromString(await t.text(),this._link.mediaType.isHTML?this._link.mediaType.essence:"text/xml")}}export{n as HttpFetcher,i as HttpResource};
|
package/dist/fetcher/Resource.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class
|
|
1
|
+
class t{constructor(e,r){this.start=e,this.endInclusive=r}}class i{readAsString(){return this.read().then(e=>e===void 0?e:new TextDecoder().decode(e))}readAsJSON(){return this.readAsString().then(e=>e===void 0?e:JSON.parse(e))}readAsXML(){return this.link().then(e=>this.readAsString().then(r=>r===void 0?r:new DOMParser().parseFromString(r,e.mediaType.isHTML?e.mediaType.essence:"text/xml")))}}export{t as NumberRange,i as Resource};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EmptyFetcher as o}from"./fetcher/Fetcher.js";import{HttpFetcher as i,HttpResource as a}from"./fetcher/HttpFetcher.js";import{NumberRange as n,Resource as p}from"./fetcher/Resource.js";import{AccessMode as x,Accessibility as l,AccessibilityProfile as s,Certification as g,Exemption as c,Feature as d,Hazard as u,PrimaryAccessMode as T}from"./publication/accessibility/Accessibility.js";import{AccessibilityMetadataDisplayGuide as y,AccessibilitySummary as C,AdditionalInformation as A,Conformance as P,HazardType as L,Hazards as N,Legal as S,Navigation as I,NonvisualReading as O,PrerecordedAudio as R,RichContent as v,RichContentType as E,VisualAdjustments as H,WaysOfReading as M}from"./publication/accessibility/AccessibilityMetadataDisplayGuide.js";import{Localization as k}from"./publication/accessibility/Localization.js";import{Encryption as F}from"./publication/encryption/Encryption.js";import{getEncryption as
|
|
1
|
+
import{EmptyFetcher as o}from"./fetcher/Fetcher.js";import{HttpFetcher as i,HttpResource as a}from"./fetcher/HttpFetcher.js";import{NumberRange as n,Resource as p}from"./fetcher/Resource.js";import{AccessMode as x,Accessibility as l,AccessibilityProfile as s,Certification as g,Exemption as c,Feature as d,Hazard as u,PrimaryAccessMode as T}from"./publication/accessibility/Accessibility.js";import{AccessibilityMetadataDisplayGuide as y,AccessibilitySummary as C,AdditionalInformation as A,Conformance as P,HazardType as L,Hazards as N,Legal as S,Navigation as I,NonvisualReading as O,PrerecordedAudio as R,RichContent as v,RichContentType as E,VisualAdjustments as H,WaysOfReading as M}from"./publication/accessibility/AccessibilityMetadataDisplayGuide.js";import{Localization as k}from"./publication/accessibility/Localization.js";import{Encryption as F}from"./publication/encryption/Encryption.js";import{getEncryption as G}from"./publication/encryption/Properties.js";import{MediaOverlay as j}from"./publication/epub/MediaOverlay.js";import{getMediaOverlay as q}from"./publication/epub/Metadata.js";import{getContains as U}from"./publication/epub/Properties.js";import{getLandmarks as Q,getListOfAudioClips as W,getListOfIllustrations as w,getListOfTables as X,getListOfVideoClips as Y,getPageList as Z}from"./publication/epub/Publication.js";import{DomRange as $}from"./publication/html/DomRange.js";import{DomRangePoint as te}from"./publication/html/DomRangePoint.js";import{getCssSelector as re,getDomRange as ie,getFragmentParameters as ae,getHtmlId as me,getPage as ne,getPartialCfi as pe,getSpace as fe,getTextFragment as xe,getTime as le}from"./publication/html/Locations.js";import{getAuthenticate as ge,getAvailability as ce,getCopies as de,getHolds as ue,getIndirectAcquisitions as Te,getNumberOfItems as be,getPrice as ye}from"./publication/opds/Properties.js";import{getImages as Ae}from"./publication/opds/Publication.js";import{buildHtmlTimeline as Le}from"./publication/services/timeline/html.js";import{buildAudioTimeline as Se}from"./publication/services/timeline/audio.js";import{Timeline as Oe}from"./publication/services/timeline/Timeline.js";import{buildTimeline as ve}from"./publication/services/timeline/index.js";import{Content as He}from"./publication/services/content/Content.js";import{TextContentTokenizer as De}from"./publication/services/content/ContentTokenizer.js";import{IllegalStateError as ze,Iterator as Fe}from"./publication/services/content/Iterator.js";import{AudioElement as Ge,ContentElement as Je,ImageElement as je,TextElement as Ve,TextSegment as qe,TextualElement as Be,VideoElement as Ue}from"./publication/services/content/element/element.js";import{Attribute as Qe,AttributeKeys as We,AttributesHolder as we}from"./publication/services/content/element/attributes.js";import{Body as Ye,Footnote as Ze,Heading as _e,TextQuote as $e}from"./publication/services/content/element/text_role.js";import{PublicationContentIterator as tt}from"./publication/services/content/iterators/PublicationContentIterator.js";import{PDFContentElement as rt,PageContentIteratorPDF as it}from"./publication/services/content/iterators/PDFTextContentIterator.js";import{HTMLResourceContentIterator as mt}from"./publication/services/content/iterators/HTMLResourceContentIterator.js";import{AltIdentifier as pt}from"./publication/AltIdentifier.js";import{BelongsTo as xt}from"./publication/BelongsTo.js";import{Contributor as st,Contributors as gt}from"./publication/Contributor.js";import{Link as dt,Links as ut}from"./publication/Link.js";import{LocalizedString as bt}from"./publication/LocalizedString.js";import{Locator as Ct,LocatorLocations as At,LocatorText as Pt}from"./publication/Locator.js";import{LocatorCollection as Nt,LocatorCollectionMetadata as St}from"./publication/LocatorCollection.js";import{Manifest as Ot}from"./publication/Manifest.js";import{Metadata as vt}from"./publication/Metadata.js";import{Profile as Ht}from"./publication/Profiles.js";import{Page as Dt,Properties as kt}from"./publication/Properties.js";import{Publication as Ft}from"./publication/Publication.js";import{PublicationCollection as Gt}from"./publication/PublicationCollection.js";import{Layout as jt}from"./publication/Layout.js";import{ReadingProgression as qt,leadingPage as Bt}from"./publication/ReadingProgression.js";import{Subject as Kt,Subjects as Qt}from"./publication/Subject.js";import{TDM as wt,TDMReservation as Xt}from"./publication/TDM.js";import{GuidedNavigationDescription as Zt,GuidedNavigationDocument as _t,GuidedNavigationObject as $t,GuidedNavigationText as eo}from"./publication/GuidedNavigation.js";import{Price as oo}from"./opds/Price.js";import{Acquisition as io}from"./opds/Acquisition.js";import{Holds as mo}from"./opds/Holds.js";import{Copies as po}from"./opds/Copies.js";import{Availability as xo,AvailabilityStatus as lo}from"./opds/Availability.js";import{MediaType as go}from"./util/mediatype/MediaType.js";import{arrayfromJSON as uo,arrayfromJSONorString as To,datefromJSON as bo,numberfromJSON as yo,positiveNumberfromJSON as Co,setToArray as Ao}from"./util/JSONParse.js";import{formatNptTime as Lo,isNptStartOfResource as No,parseNptTime as So}from"./util/npt.js";import{URITemplate as Oo}from"./util/URITemplate.js";import{DefaultTextContentTokenizer as vo,IntlTextTokenizer as Eo,NaiveTextTokenizer as Ho,TextUnit as Mo,speakableToken as Do}from"./util/tokenizer/TextTokenizer.js";export{x as AccessMode,l as Accessibility,y as AccessibilityMetadataDisplayGuide,s as AccessibilityProfile,C as AccessibilitySummary,io as Acquisition,A as AdditionalInformation,pt as AltIdentifier,Qe as Attribute,We as AttributeKeys,we as AttributesHolder,Ge as AudioElement,xo as Availability,lo as AvailabilityStatus,xt as BelongsTo,Ye as Body,g as Certification,P as Conformance,He as Content,Je as ContentElement,st as Contributor,gt as Contributors,po as Copies,vo as DefaultTextContentTokenizer,$ as DomRange,te as DomRangePoint,o as EmptyFetcher,F as Encryption,c as Exemption,d as Feature,Ze as Footnote,Zt as GuidedNavigationDescription,_t as GuidedNavigationDocument,$t as GuidedNavigationObject,eo as GuidedNavigationText,mt as HTMLResourceContentIterator,u as Hazard,L as HazardType,N as Hazards,_e as Heading,mo as Holds,i as HttpFetcher,a as HttpResource,ze as IllegalStateError,je as ImageElement,Eo as IntlTextTokenizer,Fe as Iterator,jt as Layout,S as Legal,dt as Link,ut as Links,k as Localization,bt as LocalizedString,Ct as Locator,Nt as LocatorCollection,St as LocatorCollectionMetadata,At as LocatorLocations,Pt as LocatorText,Ot as Manifest,j as MediaOverlay,go as MediaType,vt as Metadata,Ho as NaiveTextTokenizer,I as Navigation,O as NonvisualReading,n as NumberRange,rt as PDFContentElement,Dt as Page,it as PageContentIteratorPDF,R as PrerecordedAudio,oo as Price,T as PrimaryAccessMode,Ht as Profile,kt as Properties,Ft as Publication,Gt as PublicationCollection,tt as PublicationContentIterator,qt as ReadingProgression,p as Resource,v as RichContent,E as RichContentType,Kt as Subject,Qt as Subjects,wt as TDM,Xt as TDMReservation,De as TextContentTokenizer,Ve as TextElement,$e as TextQuote,qe as TextSegment,Mo as TextUnit,Be as TextualElement,Oe as Timeline,Oo as URITemplate,Ue as VideoElement,H as VisualAdjustments,M as WaysOfReading,uo as arrayfromJSON,To as arrayfromJSONorString,Se as buildAudioTimeline,Le as buildHtmlTimeline,ve as buildTimeline,bo as datefromJSON,Lo as formatNptTime,ge as getAuthenticate,ce as getAvailability,U as getContains,de as getCopies,re as getCssSelector,ie as getDomRange,G as getEncryption,ae as getFragmentParameters,ue as getHolds,me as getHtmlId,Ae as getImages,Te as getIndirectAcquisitions,Q as getLandmarks,W as getListOfAudioClips,w as getListOfIllustrations,X as getListOfTables,Y as getListOfVideoClips,q as getMediaOverlay,be as getNumberOfItems,ne as getPage,Z as getPageList,pe as getPartialCfi,ye as getPrice,fe as getSpace,xe as getTextFragment,le as getTime,No as isNptStartOfResource,Bt as leadingPage,yo as numberfromJSON,So as parseNptTime,Co as positiveNumberfromJSON,Ao as setToArray,Do as speakableToken};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{arrayfromJSONorString as a,setToArray as n}from"../util/JSONParse.js";
|
|
1
|
+
import{arrayfromJSONorString as a,setToArray as n}from"../util/JSONParse.js";class f{constructor(i){this.guided=i.guided}static deserialize(i){if(!i)return;const e=r.deserializeArray(i.guided);if(!(!e||e.length===0))return new f({guided:e})}serialize(){return{guided:this.guided.map(i=>i.serialize())}}}class d{constructor(i){this.plain=i.plain,this.ssml=i.ssml,this.language=i.language}static deserialize(i){if(i!=null){if(typeof i=="string")return i.length>0?new d({plain:i}):void 0;if(i.plain||i.ssml)return new d({plain:i.plain,ssml:i.ssml,language:i.language})}}serialize(){const i={};return this.plain!==void 0&&(i.plain=this.plain),this.ssml!==void 0&&(i.ssml=this.ssml),this.language!==void 0&&(i.language=this.language),Object.keys(i).length>0?i:void 0}}class s{constructor(i){this.audioref=i.audioref,this.imgref=i.imgref,this.textref=i.textref,this.videoref=i.videoref,this.text=i.text}static deserialize(i){if(!i)return;const e=new s({audioref:i.audioref,imgref:i.imgref,textref:i.textref,videoref:i.videoref,text:d.deserialize(i.text)});if(!(e.audioref===void 0&&e.imgref===void 0&&e.textref===void 0&&e.videoref===void 0&&e.text===void 0))return e}serialize(){const i={};this.audioref!==void 0&&(i.audioref=this.audioref),this.imgref!==void 0&&(i.imgref=this.imgref),this.textref!==void 0&&(i.textref=this.textref),this.videoref!==void 0&&(i.videoref=this.videoref);const e=this.text?.serialize();return e!==void 0&&(i.text=e),i}}class r{constructor(i){this.id=i.id,this.audioref=i.audioref,this.children=i.children,this.imgref=i.imgref,this.role=i.role,this.text=i.text,this.textref=i.textref,this.videoref=i.videoref,this.description=i.description}get plainText(){return this.text?.plain}get ssmlText(){return this.text?.ssml}get textLanguage(){return this.text?.language}static deserialize(i){if(!i)return;const e=r.deserializeArray(i.children),t=new r({id:typeof i.id=="string"?i.id:void 0,audioref:i.audioref,children:e&&e.length>0?e:void 0,imgref:i.imgref,role:i.role?new Set(a(i.role)):void 0,text:d.deserialize(i.text),textref:i.textref,videoref:i.videoref,description:s.deserialize(i.description)});if(!(t.audioref===void 0&&t.imgref===void 0&&t.textref===void 0&&t.videoref===void 0&&t.text===void 0&&t.children===void 0))return t}static deserializeArray(i){if(Array.isArray(i))return i.map(e=>r.deserialize(e)).filter(e=>e!==void 0)}serialize(){const i={};if(this.id!==void 0&&(i.id=this.id),this.audioref!==void 0&&(i.audioref=this.audioref),this.children!==void 0&&(i.children=this.children.map(e=>e.serialize())),this.imgref!==void 0&&(i.imgref=this.imgref),this.role!==void 0&&(i.role=n(this.role)),this.text!==void 0){const e=this.text.serialize();e!==void 0&&(i.text=e)}return this.textref!==void 0&&(i.textref=this.textref),this.videoref!==void 0&&(i.videoref=this.videoref),this.description!==void 0&&(i.description=this.description.serialize()),i}get audioFile(){return this.audioref?.split("#")[0]}get audioTime(){if(this.audioref?.includes("#"))return this.audioref.split("#",2)[1]}get textFile(){return this.textref?.split("#")[0]}get fragmentId(){if(this.textref?.includes("#"))return this.textref.split("#",2)[1]}get clip(){const i=this.audioFile;if(!i)return;const e=this.audioTime,t={audioResource:i,fragmentId:this.fragmentId};if(!e)return t;const o=this.parseTimer(e);return t.start=o[0],t.end=o[1],t}parseTimer(i){if(!i||!i.startsWith("t="))return[void 0,void 0];const e=i.substring(2).split(",").map(t=>parseFloat(t));return e.length===1?[isNaN(e[0])?void 0:e[0],void 0]:e.length>2?[void 0,void 0]:[isNaN(e[0])?void 0:e[0],isNaN(e[1])?void 0:e[1]]}}export{s as GuidedNavigationDescription,f as GuidedNavigationDocument,r as GuidedNavigationObject,d as GuidedNavigationText};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Metadata as k}from"./Metadata.js";import{Links as
|
|
1
|
+
import{Metadata as k}from"./Metadata.js";import{Links as n,Link as m}from"./Link.js";import{arrayfromJSONorString as g}from"../util/JSONParse.js";import{PublicationCollection as u}from"./PublicationCollection.js";import{MediaType as z}from"../util/mediatype/MediaType.js";import{Locator as O,LocatorLocations as w}from"./Locator.js";class p{constructor(e){this.context=e.context,this.metadata=e.metadata,this.links=e.links||new n([]),this.readingOrder=e.readingOrder,this.resources=e.resources,this.toc=e.toc,this.subcollections=e.subcollections}static deserialize(e){if(!e)return;const i=k.deserialize(e.metadata);if(!i)return;const t=n.deserialize(e.readingOrder?e.readingOrder:e.spine);if(!t)return;const r=new Set(["@context","metadata","links","readingOrder","spine","resources","toc"]),s={};return Object.keys(e).forEach(o=>{r.has(o)||(s[o]=e[o])}),new p({context:g(e["@context"]),metadata:i,links:n.deserialize(e.links),readingOrder:t,resources:n.deserialize(e.resources),toc:n.deserialize(e.toc),subcollections:u.deserializeCollections(s)})}serialize(){const e={};return this.context!==void 0&&(e["@context"]=this.context),e.metadata=this.metadata.serialize(),this.links&&this.links.items.length>0&&(e.links=this.links.serialize()),e.readingOrder=this.readingOrder.serialize(),this.resources&&(e.resources=this.resources.serialize()),this.toc&&(e.toc=this.toc.serialize()),u.serializeCollection(e,this.subcollections),e}linkWithRel(e){const i=new Array;i.push(this.readingOrder),this.resources&&i.push(this.resources),this.links&&i.push(this.links);let t;for(const r of i)if(t=r.findWithRel(e),t!==void 0)return t;return t}linksWithRel(e){const i=[];return i.push(this.readingOrder.filterByRel(e)),this.resources&&i.push(this.resources.filterByRel(e)),this.links&&i.push(this.links.filterByRel(e)),i.reduce((t,r)=>t.concat(r),[])}locatorFromLink(e){const i=e.href.split("#")[0],t=this.linkWithHref(i);if(!t)return;const r=t.type;if(!r)return;const s=e.href.includes("#");return new O({href:e.href,type:r,title:t.title??e.title,locations:new w({progression:s?void 0:0})})}linkWithHref(e){const i=d=>{let l;for(const a of d)if(l=a.findWithHref(e),l!==void 0)return l;const h=new Array;return d.forEach(a=>{const f=[];for(const c of a.items)c.alternates&&f.push(c.alternates),c.children&&f.push(c.children);h.push(...f)}),h.length>0&&(l=i(h)),l},t=[];t.push(this.readingOrder),this.resources&&t.push(this.resources),this.links&&t.push(this.links);const r=i(t);if(r!==void 0)return r;const s=e.split(/[#]/);if(s.length<2)return;const o=s[0];return this.linkWithHref(o)}get baseURL(){const e=this.links?.items.find(t=>t.rels&&t.rels.has("self"));if(!e)return;const i=e.href;if(i)try{const t=new URL(i);return t.search="",t.hash="",t.pathname=t.pathname.substring(0,t.pathname.lastIndexOf("/")+1),t.href}catch{return i.split(/[?#]/)[0].replace(/[^/]*$/,"")}}setSelfLink(e){this.links||(this.links=new n([])),this.links.items=this.links.items.filter(i=>i.rels===void 0||!i.rels?.has("self")),this.links.items.push(new m({href:e,type:z.READIUM_WEBPUB_MANIFEST.string,rels:new Set(["self"])}))}}export{p as Manifest};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DomRange as u}from"./DomRange.js";import{parseNptTime as h}from"../../util/npt.js";import{decodeTextFragmentDirective as d}from"@readium/helpers";function
|
|
1
|
+
import{DomRange as u}from"./DomRange.js";import{parseNptTime as h}from"../../util/npt.js";import{decodeTextFragmentDirective as d}from"@readium/helpers";function L(e){return e.otherLocations?.get("cssSelector")}function N(e){return e.otherLocations?.get("partialCfi")}function W(e){return u.deserialize(e.otherLocations?.get("domRange"))}function F(e){return e.fragments?.map(t=>d(t)).find(t=>t)}function n(e){return new Map(e.fragments?.map(t=>t.startsWith("#")?t.slice(1):t).join("&").split("&").filter(t=>!t.startsWith("#")).map(t=>t.split("=")).filter(t=>t.length===2).map(t=>[t[0].trim().toLowerCase(),t[1].trim()]))}function R(e){if(!e.fragments?.length)return;let t=e.fragments.find(r=>r.length&&!r.includes("="));if(!t){const r=n(e);r.has("id")?t=r.get("id"):r.has("name")&&(t=r.get("name"))}return t?.startsWith("#")?t.slice(1):t}function T(e){const t=parseInt(n(e).get("page"));if(!isNaN(t)&&t>=0)return t}function v(e){const t=n(e).get("t");if(t)return h(t)}function y(e){const t=n(e);if(!t.has("xywh"))return;const r=t.get("xywh");let i="pixel",s=r;const o=r.toLowerCase();o.startsWith("pixel:")?s=r.slice(6):o.startsWith("percent:")&&(i="percent",s=r.slice(8));const c=i==="percent"?parseFloat:l=>parseInt(l,10),a=s.split(",").map(c);if(a.length!==4||a.some(isNaN))return;const[g,f,m,p]=a;return{unit:i,x:g,y:f,width:m,height:p}}export{L as getCssSelector,W as getDomRange,n as getFragmentParameters,R as getHtmlId,T as getPage,N as getPartialCfi,y as getSpace,F as getTextFragment,v as getTime};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class t{constructor(e){let i,o,p=e.mediaType.replace(/\s/g,"").split(";");const s=p[0].split("/");if(s.length===2){if(i=s[0].toLowerCase().trim(),o=s[1].toLowerCase().trim(),i.length===0||o.length===0)throw new Error("Invalid media type")}else throw new Error("Invalid media type");const r={};for(let n=1;n<p.length;n++){const a=p[n].split("=");if(a.length===2){const u=a[0].toLocaleLowerCase(),f=u==="charset"?a[1].toUpperCase():a[1];r[u]=f}}const c={},m=Object.keys(r);m.sort((n,a)=>n.localeCompare(a)),m.forEach(n=>c[n]=r[n]);let l="";for(const n in c){const a=c[n];l+=`;${n}=${a}`}const g=`${i}/${o}${l}`,E=c.encoding;this.string=g,this.type=i,this.subtype=o,this.parameters=c,this.encoding=E,this.name=e.name,this.fileExtension=e.fileExtension}static parse(e){return new t(e)}get structuredSyntaxSuffix(){const e=this.subtype.split("+");return e.length>1?`+${e[e.length-1]}`:void 0}get charset(){return this.parameters.charset}contains(e){const i=typeof e=="string"?t.parse({mediaType:e}):e;if(!((this.type==="*"||this.type===i.type)&&(this.subtype==="*"||this.subtype===i.subtype)))return!1;const o=new Set(Object.entries(this.parameters).map(([s,r])=>`${s}=${r}`)),p=new Set(Object.entries(i.parameters).map(([s,r])=>`${s}=${r}`));for(const s of Array.from(o.values()))if(!p.has(s))return!1;return!0}matches(e){const i=typeof e=="string"?t.parse({mediaType:e}):e;return this.contains(i)||i.contains(this)}matchesAny(...e){for(const i of e)if(this.matches(i))return!0;return!1}equals(e){return this.string===e.string}get isZIP(){return this.matchesAny(t.ZIP,t.LCP_PROTECTED_AUDIOBOOK,t.LCP_PROTECTED_PDF)||this.structuredSyntaxSuffix==="+zip"}get isJSON(){return this.matchesAny(t.JSON)||this.structuredSyntaxSuffix==="+json"}get isOPDS(){return this.matchesAny(t.OPDS1,t.OPDS1_ENTRY,t.OPDS2,t.OPDS2_PUBLICATION,t.OPDS_AUTHENTICATION)||this.structuredSyntaxSuffix==="+json"}get isHTML(){return this.matchesAny(t.HTML,t.XHTML)}get isBitmap(){return this.matchesAny(t.AVIF,t.BMP,t.GIF,t.JPEG,t.PNG,t.TIFF,t.WEBP)}get isAudio(){return this.type==="audio"}get isVideo(){return this.type==="video"}get isRWPM(){return this.matchesAny(t.READIUM_AUDIOBOOK_MANIFEST,t.DIVINA_MANIFEST,t.READIUM_WEBPUB_MANIFEST)}get isPublication(){return this.matchesAny(t.READIUM_AUDIOBOOK,t.READIUM_AUDIOBOOK_MANIFEST,t.CBZ,t.DIVINA,t.DIVINA_MANIFEST,t.EPUB,t.LCP_PROTECTED_AUDIOBOOK,t.LCP_PROTECTED_PDF,t.LPF,t.PDF,t.W3C_WPUB_MANIFEST,t.READIUM_WEBPUB,t.READIUM_WEBPUB_MANIFEST,t.ZAB)}static get AAC(){return t.parse({mediaType:"audio/aac",fileExtension:"aac"})}static get ACSM(){return t.parse({mediaType:"application/vnd.adobe.adept+xml",name:"Adobe Content Server Message",fileExtension:"acsm"})}static get AIFF(){return t.parse({mediaType:"audio/aiff",fileExtension:"aiff"})}static get AVI(){return t.parse({mediaType:"video/x-msvideo",fileExtension:"avi"})}static get AVIF(){return t.parse({mediaType:"image/avif",fileExtension:"avif"})}static get BINARY(){return t.parse({mediaType:"application/octet-stream"})}static get BMP(){return t.parse({mediaType:"image/bmp",fileExtension:"bmp"})}static get CBZ(){return t.parse({mediaType:"application/vnd.comicbook+zip",name:"Comic Book Archive",fileExtension:"cbz"})}static get CSS(){return t.parse({mediaType:"text/css",fileExtension:"css"})}static get DIVINA(){return t.parse({mediaType:"application/divina+zip",name:"Digital Visual Narratives",fileExtension:"divina"})}static get DIVINA_MANIFEST(){return t.parse({mediaType:"application/divina+json",name:"Digital Visual Narratives",fileExtension:"json"})}static get EPUB(){return t.parse({mediaType:"application/epub+zip",name:"EPUB",fileExtension:"epub"})}static get GIF(){return t.parse({mediaType:"image/gif",fileExtension:"gif"})}static get GZ(){return t.parse({mediaType:"application/gzip",fileExtension:"gz"})}static get HTML(){return t.parse({mediaType:"text/html",fileExtension:"html"})}static get JAVASCRIPT(){return t.parse({mediaType:"text/javascript",fileExtension:"js"})}static get JPEG(){return t.parse({mediaType:"image/jpeg",fileExtension:"jpeg"})}static get JSON(){return t.parse({mediaType:"application/json"})}static get LCP_LICENSE_DOCUMENT(){return t.parse({mediaType:"application/vnd.readium.lcp.license.v1.0+json",name:"LCP License",fileExtension:"lcpl"})}static get LCP_PROTECTED_AUDIOBOOK(){return t.parse({mediaType:"application/audiobook+lcp",name:"LCP Protected Audiobook",fileExtension:"lcpa"})}static get LCP_PROTECTED_PDF(){return t.parse({mediaType:"application/pdf+lcp",name:"LCP Protected PDF",fileExtension:"lcpdf"})}static get LCP_STATUS_DOCUMENT(){return t.parse({mediaType:"application/vnd.readium.license.status.v1.0+json"})}static get LPF(){return t.parse({mediaType:"application/lpf+zip",fileExtension:"lpf"})}static get MP3(){return t.parse({mediaType:"audio/mpeg",fileExtension:"mp3"})}static get MPEG(){return t.parse({mediaType:"video/mpeg",fileExtension:"mpeg"})}static get NCX(){return t.parse({mediaType:"application/x-dtbncx+xml",fileExtension:"ncx"})}static get OGG(){return t.parse({mediaType:"audio/ogg",fileExtension:"oga"})}static get OGV(){return t.parse({mediaType:"video/ogg",fileExtension:"ogv"})}static get OPDS1(){return t.parse({mediaType:"application/atom+xml;profile=opds-catalog"})}static get OPDS1_ENTRY(){return t.parse({mediaType:"application/atom+xml;type=entry;profile=opds-catalog"})}static get OPDS2(){return t.parse({mediaType:"application/opds+json"})}static get OPDS2_PUBLICATION(){return t.parse({mediaType:"application/opds-publication+json"})}static get OPDS_AUTHENTICATION(){return t.parse({mediaType:"application/opds-authentication+json"})}static get OPUS(){return t.parse({mediaType:"audio/opus",fileExtension:"opus"})}static get OTF(){return t.parse({mediaType:"font/otf",fileExtension:"otf"})}static get PDF(){return t.parse({mediaType:"application/pdf",name:"PDF",fileExtension:"pdf"})}static get PNG(){return t.parse({mediaType:"image/png",fileExtension:"png"})}static get READIUM_AUDIOBOOK(){return t.parse({mediaType:"application/audiobook+zip",name:"Readium Audiobook",fileExtension:"audiobook"})}static get READIUM_AUDIOBOOK_MANIFEST(){return t.parse({mediaType:"application/audiobook+json",name:"Readium Audiobook",fileExtension:"json"})}static get READIUM_CONTENT_DOCUMENT(){return t.parse({mediaType:"application/vnd.readium.content+json",name:"Readium Content Document",fileExtension:"json"})}static get READIUM_GUIDED_NAVIGATION_DOCUMENT(){return t.parse({mediaType:"application/guided-navigation+json",name:"Readium Guided Navigation Document",fileExtension:"json"})}static get READIUM_POSITION_LIST(){return t.parse({mediaType:"application/vnd.readium.position-list+json",name:"Readium Position List",fileExtension:"json"})}static get READIUM_WEBPUB(){return t.parse({mediaType:"application/webpub+zip",name:"Readium Web Publication",fileExtension:"webpub"})}static get READIUM_WEBPUB_MANIFEST(){return t.parse({mediaType:"application/webpub+json",name:"Readium Web Publication",fileExtension:"json"})}static get SMIL(){return t.parse({mediaType:"application/smil+xml",fileExtension:"smil"})}static get SVG(){return t.parse({mediaType:"image/svg+xml",fileExtension:"svg"})}static get TEXT(){return t.parse({mediaType:"text/plain",fileExtension:"txt"})}static get TIFF(){return t.parse({mediaType:"image/tiff",fileExtension:"tiff"})}static get TTF(){return t.parse({mediaType:"font/ttf",fileExtension:"ttf"})}static get W3C_WPUB_MANIFEST(){return t.parse({mediaType:"application/x.readium.w3c.wpub+json",name:"Web Publication",fileExtension:"json"})}static get WAV(){return t.parse({mediaType:"audio/wav",fileExtension:"wav"})}static get WEBM_AUDIO(){return t.parse({mediaType:"audio/webm",fileExtension:"webm"})}static get WEBM_VIDEO(){return t.parse({mediaType:"video/webm",fileExtension:"webm"})}static get WEBP(){return t.parse({mediaType:"image/webp",fileExtension:"webp"})}static get WOFF(){return t.parse({mediaType:"font/woff",fileExtension:"woff"})}static get WOFF2(){return t.parse({mediaType:"font/woff2",fileExtension:"woff2"})}static get XHTML(){return t.parse({mediaType:"application/xhtml+xml",fileExtension:"xhtml"})}static get XML(){return t.parse({mediaType:"application/xml",fileExtension:"xml"})}static get ZAB(){return t.parse({mediaType:"application/x.readium.zab+zip",name:"Zipped Audio Book",fileExtension:"zab"})}static get ZIP(){return t.parse({mediaType:"application/zip",fileExtension:"zip"})}}export{t as MediaType};
|
|
1
|
+
class t{constructor(e){let i,o,p=e.mediaType.replace(/\s/g,"").split(";");const s=p[0].split("/");if(s.length===2){if(i=s[0].toLowerCase().trim(),o=s[1].toLowerCase().trim(),i.length===0||o.length===0)throw new Error("Invalid media type")}else throw new Error("Invalid media type");const r={};for(let n=1;n<p.length;n++){const a=p[n].split("=");if(a.length===2){const u=a[0].toLocaleLowerCase(),f=u==="charset"?a[1].toUpperCase():a[1];r[u]=f}}const c={},m=Object.keys(r);m.sort((n,a)=>n.localeCompare(a)),m.forEach(n=>c[n]=r[n]);let l="";for(const n in c){const a=c[n];l+=`;${n}=${a}`}const g=`${i}/${o}${l}`,E=c.encoding;this.string=g,this.type=i,this.subtype=o,this.parameters=c,this.encoding=E,this.name=e.name,this.fileExtension=e.fileExtension}static parse(e){return new t(e)}get structuredSyntaxSuffix(){const e=this.subtype.split("+");return e.length>1?`+${e[e.length-1]}`:void 0}get essence(){return`${this.type}/${this.subtype}`}get charset(){return this.parameters.charset}contains(e){const i=typeof e=="string"?t.parse({mediaType:e}):e;if(!((this.type==="*"||this.type===i.type)&&(this.subtype==="*"||this.subtype===i.subtype)))return!1;const o=new Set(Object.entries(this.parameters).map(([s,r])=>`${s}=${r}`)),p=new Set(Object.entries(i.parameters).map(([s,r])=>`${s}=${r}`));for(const s of Array.from(o.values()))if(!p.has(s))return!1;return!0}matches(e){const i=typeof e=="string"?t.parse({mediaType:e}):e;return this.contains(i)||i.contains(this)}matchesAny(...e){for(const i of e)if(this.matches(i))return!0;return!1}equals(e){return this.string===e.string}get isZIP(){return this.matchesAny(t.ZIP,t.LCP_PROTECTED_AUDIOBOOK,t.LCP_PROTECTED_PDF)||this.structuredSyntaxSuffix==="+zip"}get isJSON(){return this.matchesAny(t.JSON)||this.structuredSyntaxSuffix==="+json"}get isOPDS(){return this.matchesAny(t.OPDS1,t.OPDS1_ENTRY,t.OPDS2,t.OPDS2_PUBLICATION,t.OPDS_AUTHENTICATION)||this.structuredSyntaxSuffix==="+json"}get isHTML(){return this.matchesAny(t.HTML,t.XHTML)}get isBitmap(){return this.matchesAny(t.AVIF,t.BMP,t.GIF,t.JPEG,t.PNG,t.TIFF,t.WEBP)}get isAudio(){return this.type==="audio"}get isVideo(){return this.type==="video"}get isRWPM(){return this.matchesAny(t.READIUM_AUDIOBOOK_MANIFEST,t.DIVINA_MANIFEST,t.READIUM_WEBPUB_MANIFEST)}get isPublication(){return this.matchesAny(t.READIUM_AUDIOBOOK,t.READIUM_AUDIOBOOK_MANIFEST,t.CBZ,t.DIVINA,t.DIVINA_MANIFEST,t.EPUB,t.LCP_PROTECTED_AUDIOBOOK,t.LCP_PROTECTED_PDF,t.LPF,t.PDF,t.W3C_WPUB_MANIFEST,t.READIUM_WEBPUB,t.READIUM_WEBPUB_MANIFEST,t.ZAB)}static get AAC(){return t.parse({mediaType:"audio/aac",fileExtension:"aac"})}static get ACSM(){return t.parse({mediaType:"application/vnd.adobe.adept+xml",name:"Adobe Content Server Message",fileExtension:"acsm"})}static get AIFF(){return t.parse({mediaType:"audio/aiff",fileExtension:"aiff"})}static get AVI(){return t.parse({mediaType:"video/x-msvideo",fileExtension:"avi"})}static get AVIF(){return t.parse({mediaType:"image/avif",fileExtension:"avif"})}static get BINARY(){return t.parse({mediaType:"application/octet-stream"})}static get BMP(){return t.parse({mediaType:"image/bmp",fileExtension:"bmp"})}static get CBZ(){return t.parse({mediaType:"application/vnd.comicbook+zip",name:"Comic Book Archive",fileExtension:"cbz"})}static get CSS(){return t.parse({mediaType:"text/css",fileExtension:"css"})}static get DIVINA(){return t.parse({mediaType:"application/divina+zip",name:"Digital Visual Narratives",fileExtension:"divina"})}static get DIVINA_MANIFEST(){return t.parse({mediaType:"application/divina+json",name:"Digital Visual Narratives",fileExtension:"json"})}static get EPUB(){return t.parse({mediaType:"application/epub+zip",name:"EPUB",fileExtension:"epub"})}static get GIF(){return t.parse({mediaType:"image/gif",fileExtension:"gif"})}static get GZ(){return t.parse({mediaType:"application/gzip",fileExtension:"gz"})}static get HTML(){return t.parse({mediaType:"text/html",fileExtension:"html"})}static get JAVASCRIPT(){return t.parse({mediaType:"text/javascript",fileExtension:"js"})}static get JPEG(){return t.parse({mediaType:"image/jpeg",fileExtension:"jpeg"})}static get JSON(){return t.parse({mediaType:"application/json"})}static get LCP_LICENSE_DOCUMENT(){return t.parse({mediaType:"application/vnd.readium.lcp.license.v1.0+json",name:"LCP License",fileExtension:"lcpl"})}static get LCP_PROTECTED_AUDIOBOOK(){return t.parse({mediaType:"application/audiobook+lcp",name:"LCP Protected Audiobook",fileExtension:"lcpa"})}static get LCP_PROTECTED_PDF(){return t.parse({mediaType:"application/pdf+lcp",name:"LCP Protected PDF",fileExtension:"lcpdf"})}static get LCP_STATUS_DOCUMENT(){return t.parse({mediaType:"application/vnd.readium.license.status.v1.0+json"})}static get LPF(){return t.parse({mediaType:"application/lpf+zip",fileExtension:"lpf"})}static get MP3(){return t.parse({mediaType:"audio/mpeg",fileExtension:"mp3"})}static get MPEG(){return t.parse({mediaType:"video/mpeg",fileExtension:"mpeg"})}static get NCX(){return t.parse({mediaType:"application/x-dtbncx+xml",fileExtension:"ncx"})}static get OGG(){return t.parse({mediaType:"audio/ogg",fileExtension:"oga"})}static get OGV(){return t.parse({mediaType:"video/ogg",fileExtension:"ogv"})}static get OPDS1(){return t.parse({mediaType:"application/atom+xml;profile=opds-catalog"})}static get OPDS1_ENTRY(){return t.parse({mediaType:"application/atom+xml;type=entry;profile=opds-catalog"})}static get OPDS2(){return t.parse({mediaType:"application/opds+json"})}static get OPDS2_PUBLICATION(){return t.parse({mediaType:"application/opds-publication+json"})}static get OPDS_AUTHENTICATION(){return t.parse({mediaType:"application/opds-authentication+json"})}static get OPUS(){return t.parse({mediaType:"audio/opus",fileExtension:"opus"})}static get OTF(){return t.parse({mediaType:"font/otf",fileExtension:"otf"})}static get PDF(){return t.parse({mediaType:"application/pdf",name:"PDF",fileExtension:"pdf"})}static get PNG(){return t.parse({mediaType:"image/png",fileExtension:"png"})}static get READIUM_AUDIOBOOK(){return t.parse({mediaType:"application/audiobook+zip",name:"Readium Audiobook",fileExtension:"audiobook"})}static get READIUM_AUDIOBOOK_MANIFEST(){return t.parse({mediaType:"application/audiobook+json",name:"Readium Audiobook",fileExtension:"json"})}static get READIUM_CONTENT_DOCUMENT(){return t.parse({mediaType:"application/vnd.readium.content+json",name:"Readium Content Document",fileExtension:"json"})}static get READIUM_GUIDED_NAVIGATION_DOCUMENT(){return t.parse({mediaType:"application/guided-navigation+json",name:"Readium Guided Navigation Document",fileExtension:"json"})}static get READIUM_POSITION_LIST(){return t.parse({mediaType:"application/vnd.readium.position-list+json",name:"Readium Position List",fileExtension:"json"})}static get READIUM_WEBPUB(){return t.parse({mediaType:"application/webpub+zip",name:"Readium Web Publication",fileExtension:"webpub"})}static get READIUM_WEBPUB_MANIFEST(){return t.parse({mediaType:"application/webpub+json",name:"Readium Web Publication",fileExtension:"json"})}static get SMIL(){return t.parse({mediaType:"application/smil+xml",fileExtension:"smil"})}static get SVG(){return t.parse({mediaType:"image/svg+xml",fileExtension:"svg"})}static get TEXT(){return t.parse({mediaType:"text/plain",fileExtension:"txt"})}static get TIFF(){return t.parse({mediaType:"image/tiff",fileExtension:"tiff"})}static get TTF(){return t.parse({mediaType:"font/ttf",fileExtension:"ttf"})}static get W3C_WPUB_MANIFEST(){return t.parse({mediaType:"application/x.readium.w3c.wpub+json",name:"Web Publication",fileExtension:"json"})}static get WAV(){return t.parse({mediaType:"audio/wav",fileExtension:"wav"})}static get WEBM_AUDIO(){return t.parse({mediaType:"audio/webm",fileExtension:"webm"})}static get WEBM_VIDEO(){return t.parse({mediaType:"video/webm",fileExtension:"webm"})}static get WEBP(){return t.parse({mediaType:"image/webp",fileExtension:"webp"})}static get WOFF(){return t.parse({mediaType:"font/woff",fileExtension:"woff"})}static get WOFF2(){return t.parse({mediaType:"font/woff2",fileExtension:"woff2"})}static get XHTML(){return t.parse({mediaType:"application/xhtml+xml",fileExtension:"xhtml"})}static get XML(){return t.parse({mediaType:"application/xml",fileExtension:"xml"})}static get ZAB(){return t.parse({mediaType:"application/x.readium.zab+zip",name:"Zipped Audio Book",fileExtension:"zab"})}static get ZIP(){return t.parse({mediaType:"application/zip",fileExtension:"zip"})}}export{t as MediaType};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@readium/shared",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.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",
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
},
|
|
57
57
|
"sideEffects": false,
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@readium/helpers": "1.
|
|
59
|
+
"@readium/helpers": "1.2.0"
|
|
60
60
|
},
|
|
61
61
|
"files": [
|
|
62
62
|
"dist",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"types"
|
|
65
65
|
],
|
|
66
66
|
"engines": {
|
|
67
|
-
"node": ">=
|
|
67
|
+
"node": ">=24"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"@babel/core": "^7.28.6",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Link } from '../publication/Link.ts';
|
|
2
2
|
import { Fetcher } from './Fetcher.ts';
|
|
3
|
-
import { NumberRange, Resource } from './Resource.ts';
|
|
3
|
+
import { NumberRange, Resource, ResourceReadOptions } from './Resource.ts';
|
|
4
4
|
|
|
5
5
|
export type FetchImplementation = (
|
|
6
6
|
input: RequestInfo | URL,
|
|
@@ -72,9 +72,9 @@ export class HttpResource implements Resource {
|
|
|
72
72
|
return this._link; // TODO mediatype alteration. Need http response mediatype sniffer stuff
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
async read(range?: NumberRange): Promise<Uint8Array | undefined> {
|
|
75
|
+
async read(range?: NumberRange, options?: ResourceReadOptions): Promise<Uint8Array | undefined> {
|
|
76
76
|
if (range) throw new Error('http read range not implemented!'); // TODO
|
|
77
|
-
const resp = await this.client(this.url);
|
|
77
|
+
const resp = await this.client(this.url, options?.signal ? { signal: options.signal } : undefined);
|
|
78
78
|
if (!resp.ok)
|
|
79
79
|
throw new Error(
|
|
80
80
|
`http GET request for ${this.url} failed with HTTP status code ${resp.status}`
|
|
@@ -108,7 +108,7 @@ export class HttpResource implements Resource {
|
|
|
108
108
|
return await resp.text();
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
async readAsXML(): Promise<
|
|
111
|
+
async readAsXML(): Promise<Document> {
|
|
112
112
|
const resp = await this.client(this.url);
|
|
113
113
|
if (!resp.ok)
|
|
114
114
|
throw new Error(
|
|
@@ -116,7 +116,7 @@ export class HttpResource implements Resource {
|
|
|
116
116
|
); // TODO
|
|
117
117
|
return new DOMParser().parseFromString(
|
|
118
118
|
await resp.text(),
|
|
119
|
-
'application/xml'
|
|
119
|
+
this._link.mediaType.isHTML ? (this._link.mediaType.essence as 'application/xhtml+xml' | 'text/html') : 'text/xml'
|
|
120
120
|
);
|
|
121
121
|
}
|
|
122
122
|
}
|
package/src/fetcher/Resource.ts
CHANGED
|
@@ -11,10 +11,15 @@ export class NumberRange {
|
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
export interface ResourceReadOptions {
|
|
15
|
+
/** Aborts the underlying request, e.g. when a prefetched resource is no longer needed */
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
export abstract class Resource {
|
|
15
20
|
abstract link(): Promise<Link>;
|
|
16
21
|
abstract length(): Promise<number | undefined>; // TODO make try?
|
|
17
|
-
abstract read(range?: NumberRange): Promise<Uint8Array | undefined>;
|
|
22
|
+
abstract read(range?: NumberRange, options?: ResourceReadOptions): Promise<Uint8Array | undefined>;
|
|
18
23
|
readAsString(): Promise<string | undefined> {
|
|
19
24
|
return this.read().then(bytes => {
|
|
20
25
|
if (bytes === undefined) return bytes;
|
|
@@ -27,11 +32,11 @@ export abstract class Resource {
|
|
|
27
32
|
return JSON.parse(str);
|
|
28
33
|
});
|
|
29
34
|
}
|
|
30
|
-
readAsXML(): Promise<
|
|
31
|
-
return this.readAsString().then(str => {
|
|
35
|
+
readAsXML(): Promise<Document | undefined> {
|
|
36
|
+
return this.link().then(l => this.readAsString().then(str => {
|
|
32
37
|
if (str === undefined) return str;
|
|
33
|
-
return new DOMParser().parseFromString(str, 'text/xml');
|
|
34
|
-
});
|
|
38
|
+
return new DOMParser().parseFromString(str, l.mediaType.isHTML ? (l.mediaType.essence as 'application/xhtml+xml' | 'text/html') : 'text/xml');
|
|
39
|
+
}));
|
|
35
40
|
}
|
|
36
41
|
abstract close(): void;
|
|
37
42
|
}
|
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
arrayfromJSONorString,
|
|
3
3
|
setToArray,
|
|
4
4
|
} from '../util/JSONParse.ts';
|
|
5
|
-
import { Links } from "./Link.ts";
|
|
6
5
|
|
|
7
6
|
export interface Clip {
|
|
8
7
|
audioResource: string;
|
|
@@ -16,35 +15,34 @@ export interface Clip {
|
|
|
16
15
|
* https://readium.org/guided-navigation/schema/document.schema.json
|
|
17
16
|
*/
|
|
18
17
|
export class GuidedNavigationDocument {
|
|
19
|
-
|
|
20
|
-
public readonly guided
|
|
18
|
+
/** Non-empty sequence of objects meant to be presented sequentially to the user. */
|
|
19
|
+
public readonly guided: GuidedNavigationObject[];
|
|
21
20
|
|
|
22
21
|
constructor(values: {
|
|
23
|
-
|
|
24
|
-
guided?: GuidedNavigationObject[];
|
|
22
|
+
guided: GuidedNavigationObject[];
|
|
25
23
|
}) {
|
|
26
|
-
this.links = values.links;
|
|
27
24
|
this.guided = values.guided;
|
|
28
25
|
}
|
|
29
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Deserializes a GuidedNavigationDocument from JSON.
|
|
29
|
+
* Returns undefined if `guided` is missing or has no valid object.
|
|
30
|
+
*/
|
|
30
31
|
public static deserialize(json: any): GuidedNavigationDocument | undefined {
|
|
31
32
|
if (!json) return;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
});
|
|
33
|
+
const guided = GuidedNavigationObject.deserializeArray(json.guided);
|
|
34
|
+
if (!guided || guided.length === 0) return;
|
|
35
|
+
return new GuidedNavigationDocument({ guided });
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
public serialize(): any {
|
|
39
|
-
|
|
40
|
-
if (this.links !== undefined) json.links = this.links.serialize();
|
|
41
|
-
if (this.guided !== undefined) json.guided = this.guided.map(x => x.serialize());
|
|
42
|
-
return json;
|
|
39
|
+
return { guided: this.guided.map(x => x.serialize()) };
|
|
43
40
|
}
|
|
44
41
|
}
|
|
45
42
|
|
|
46
43
|
/**
|
|
47
44
|
* Represents a text value containing plain text, SSML, and language information.
|
|
45
|
+
* https://readium.org/guided-navigation/schema/text.schema.json
|
|
48
46
|
*/
|
|
49
47
|
export class GuidedNavigationText {
|
|
50
48
|
/** Plain text content */
|
|
@@ -76,11 +74,11 @@ export class GuidedNavigationText {
|
|
|
76
74
|
if (json === undefined || json === null) return undefined;
|
|
77
75
|
|
|
78
76
|
if (typeof json === 'string') {
|
|
79
|
-
return new GuidedNavigationText({ plain: json });
|
|
77
|
+
return json.length > 0 ? new GuidedNavigationText({ plain: json }) : undefined;
|
|
80
78
|
}
|
|
81
79
|
|
|
82
|
-
//
|
|
83
|
-
if (json.plain || json.ssml
|
|
80
|
+
// The schema requires a non-empty `plain` or `ssml`
|
|
81
|
+
if (json.plain || json.ssml) {
|
|
84
82
|
return new GuidedNavigationText({
|
|
85
83
|
plain: json.plain,
|
|
86
84
|
ssml: json.ssml,
|
|
@@ -104,11 +102,82 @@ export class GuidedNavigationText {
|
|
|
104
102
|
}
|
|
105
103
|
|
|
106
104
|
/**
|
|
107
|
-
* Guided Navigation Object
|
|
108
|
-
* https://
|
|
105
|
+
* Text, audio, image or video description of a Guided Navigation Object.
|
|
106
|
+
* https://readium.org/guided-navigation/schema/description.schema.json
|
|
109
107
|
*/
|
|
108
|
+
export class GuidedNavigationDescription {
|
|
109
|
+
/** References an audio resource or a fragment of it. */
|
|
110
|
+
public readonly audioref?: string;
|
|
111
|
+
|
|
112
|
+
/** References an image or a fragment of it. */
|
|
113
|
+
public readonly imgref?: string;
|
|
114
|
+
|
|
115
|
+
/** References a textual resource or a fragment of it. */
|
|
116
|
+
public readonly textref?: string;
|
|
117
|
+
|
|
118
|
+
/** References a video resource or a fragment of it. */
|
|
119
|
+
public readonly videoref?: string;
|
|
120
|
+
|
|
121
|
+
/** Textual description. */
|
|
122
|
+
public readonly text?: GuidedNavigationText;
|
|
123
|
+
|
|
124
|
+
constructor(values: {
|
|
125
|
+
audioref?: string;
|
|
126
|
+
imgref?: string;
|
|
127
|
+
textref?: string;
|
|
128
|
+
videoref?: string;
|
|
129
|
+
text?: GuidedNavigationText;
|
|
130
|
+
}) {
|
|
131
|
+
this.audioref = values.audioref;
|
|
132
|
+
this.imgref = values.imgref;
|
|
133
|
+
this.textref = values.textref;
|
|
134
|
+
this.videoref = values.videoref;
|
|
135
|
+
this.text = values.text;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Deserializes a GuidedNavigationDescription from JSON.
|
|
140
|
+
* Returns undefined if it has none of the refs nor text.
|
|
141
|
+
*/
|
|
142
|
+
public static deserialize(json: any): GuidedNavigationDescription | undefined {
|
|
143
|
+
if (!json) return undefined;
|
|
144
|
+
const description = new GuidedNavigationDescription({
|
|
145
|
+
audioref: json.audioref,
|
|
146
|
+
imgref: json.imgref,
|
|
147
|
+
textref: json.textref,
|
|
148
|
+
videoref: json.videoref,
|
|
149
|
+
text: GuidedNavigationText.deserialize(json.text)
|
|
150
|
+
});
|
|
151
|
+
if (
|
|
152
|
+
description.audioref === undefined &&
|
|
153
|
+
description.imgref === undefined &&
|
|
154
|
+
description.textref === undefined &&
|
|
155
|
+
description.videoref === undefined &&
|
|
156
|
+
description.text === undefined
|
|
157
|
+
) return undefined;
|
|
158
|
+
return description;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
public serialize(): any {
|
|
162
|
+
const json: any = {};
|
|
163
|
+
if (this.audioref !== undefined) json.audioref = this.audioref;
|
|
164
|
+
if (this.imgref !== undefined) json.imgref = this.imgref;
|
|
165
|
+
if (this.textref !== undefined) json.textref = this.textref;
|
|
166
|
+
if (this.videoref !== undefined) json.videoref = this.videoref;
|
|
167
|
+
const text = this.text?.serialize();
|
|
168
|
+
if (text !== undefined) json.text = text;
|
|
169
|
+
return json;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
110
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Guided Navigation Object
|
|
175
|
+
* https://readium.org/guided-navigation/schema/document.schema.json
|
|
176
|
+
*/
|
|
111
177
|
export class GuidedNavigationObject {
|
|
178
|
+
/** Identifier of the object. */
|
|
179
|
+
public readonly id?: string;
|
|
180
|
+
|
|
112
181
|
/** References an audio resource or a fragment of it. */
|
|
113
182
|
public readonly audioref?: string;
|
|
114
183
|
|
|
@@ -121,13 +190,6 @@ export class GuidedNavigationObject {
|
|
|
121
190
|
/** Convey the structural semantics of a publication. */
|
|
122
191
|
public readonly role?: Set<string>;
|
|
123
192
|
|
|
124
|
-
/**
|
|
125
|
-
* Indicates the heading level (1-6) for the navigation object.
|
|
126
|
-
* @minimum 1
|
|
127
|
-
* @maximum 6
|
|
128
|
-
*/
|
|
129
|
-
public readonly level?: number;
|
|
130
|
-
|
|
131
193
|
/**
|
|
132
194
|
* Textual equivalent of the resources or fragment of the resources referenced by the current Guided Navigation Object.
|
|
133
195
|
*/
|
|
@@ -136,32 +198,34 @@ export class GuidedNavigationObject {
|
|
|
136
198
|
/** References a textual resource or a fragment of it. */
|
|
137
199
|
public readonly textref?: string;
|
|
138
200
|
|
|
139
|
-
/**
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
public readonly description?:
|
|
201
|
+
/** References a video resource or a fragment of it. */
|
|
202
|
+
public readonly videoref?: string;
|
|
203
|
+
|
|
204
|
+
/** Text, audio, image or video description of the current Guided Navigation Object. */
|
|
205
|
+
public readonly description?: GuidedNavigationDescription;
|
|
144
206
|
|
|
145
207
|
/**
|
|
146
208
|
* Creates a [GuidedNavigation] object.
|
|
147
209
|
*/
|
|
148
210
|
constructor(values: {
|
|
211
|
+
id?: string;
|
|
149
212
|
audioref?: string;
|
|
150
213
|
children?: GuidedNavigationObject[];
|
|
151
214
|
imgref?: string;
|
|
152
215
|
role?: Set<string>;
|
|
153
|
-
level?: number;
|
|
154
216
|
text?: GuidedNavigationText;
|
|
155
217
|
textref?: string;
|
|
156
|
-
|
|
218
|
+
videoref?: string;
|
|
219
|
+
description?: GuidedNavigationDescription;
|
|
157
220
|
}) {
|
|
221
|
+
this.id = values.id;
|
|
158
222
|
this.audioref = values.audioref;
|
|
159
223
|
this.children = values.children;
|
|
160
224
|
this.imgref = values.imgref;
|
|
161
225
|
this.role = values.role;
|
|
162
|
-
this.level = values.level !== undefined ? Math.min(6, Math.max(1, values.level)) : undefined;
|
|
163
226
|
this.text = values.text;
|
|
164
227
|
this.textref = values.textref;
|
|
228
|
+
this.videoref = values.videoref;
|
|
165
229
|
this.description = values.description;
|
|
166
230
|
}
|
|
167
231
|
|
|
@@ -188,23 +252,35 @@ export class GuidedNavigationObject {
|
|
|
188
252
|
}
|
|
189
253
|
|
|
190
254
|
/**
|
|
191
|
-
* Deserializes a GuidedNavigationObject from JSON
|
|
255
|
+
* Deserializes a GuidedNavigationObject from JSON.
|
|
256
|
+
* Returns undefined if it has none of the refs, text, nor children.
|
|
192
257
|
*/
|
|
193
258
|
public static deserialize(json: any): GuidedNavigationObject | undefined {
|
|
194
259
|
if (!json) return undefined;
|
|
195
260
|
|
|
196
|
-
|
|
261
|
+
const children = GuidedNavigationObject.deserializeArray(json.children);
|
|
262
|
+
const obj = new GuidedNavigationObject({
|
|
263
|
+
id: typeof json.id === 'string' ? json.id : undefined,
|
|
197
264
|
audioref: json.audioref,
|
|
198
|
-
children:
|
|
265
|
+
children: children && children.length > 0 ? children : undefined,
|
|
199
266
|
imgref: json.imgref,
|
|
200
267
|
role: json.role
|
|
201
268
|
? new Set<string>(arrayfromJSONorString(json.role))
|
|
202
269
|
: undefined,
|
|
203
|
-
level: typeof json.level === 'number' ? json.level : undefined,
|
|
204
270
|
text: GuidedNavigationText.deserialize(json.text),
|
|
205
271
|
textref: json.textref,
|
|
206
|
-
|
|
272
|
+
videoref: json.videoref,
|
|
273
|
+
description: GuidedNavigationDescription.deserialize(json.description)
|
|
207
274
|
});
|
|
275
|
+
if (
|
|
276
|
+
obj.audioref === undefined &&
|
|
277
|
+
obj.imgref === undefined &&
|
|
278
|
+
obj.textref === undefined &&
|
|
279
|
+
obj.videoref === undefined &&
|
|
280
|
+
obj.text === undefined &&
|
|
281
|
+
obj.children === undefined
|
|
282
|
+
) return undefined;
|
|
283
|
+
return obj;
|
|
208
284
|
}
|
|
209
285
|
|
|
210
286
|
/**
|
|
@@ -213,8 +289,8 @@ export class GuidedNavigationObject {
|
|
|
213
289
|
public static deserializeArray(json: any): GuidedNavigationObject[] | undefined {
|
|
214
290
|
if (!(Array.isArray(json))) return undefined;
|
|
215
291
|
return json
|
|
216
|
-
.map
|
|
217
|
-
.filter((x) => x !== undefined);
|
|
292
|
+
.map((item) => GuidedNavigationObject.deserialize(item))
|
|
293
|
+
.filter((x): x is GuidedNavigationObject => x !== undefined);
|
|
218
294
|
}
|
|
219
295
|
|
|
220
296
|
/**
|
|
@@ -222,11 +298,11 @@ export class GuidedNavigationObject {
|
|
|
222
298
|
*/
|
|
223
299
|
public serialize(): any {
|
|
224
300
|
const json: any = {};
|
|
301
|
+
if (this.id !== undefined) json.id = this.id;
|
|
225
302
|
if (this.audioref !== undefined) json.audioref = this.audioref;
|
|
226
303
|
if (this.children !== undefined) json.children = this.children.map(x => x.serialize());
|
|
227
304
|
if (this.imgref !== undefined) json.imgref = this.imgref;
|
|
228
305
|
if (this.role !== undefined) json.role = setToArray(this.role);
|
|
229
|
-
if (this.level !== undefined) json.level = this.level;
|
|
230
306
|
if (this.text !== undefined) {
|
|
231
307
|
const serializedText = this.text.serialize();
|
|
232
308
|
if (serializedText !== undefined) {
|
|
@@ -234,9 +310,8 @@ export class GuidedNavigationObject {
|
|
|
234
310
|
}
|
|
235
311
|
}
|
|
236
312
|
if (this.textref !== undefined) json.textref = this.textref;
|
|
237
|
-
if (this.
|
|
238
|
-
|
|
239
|
-
}
|
|
313
|
+
if (this.videoref !== undefined) json.videoref = this.videoref;
|
|
314
|
+
if (this.description !== undefined) json.description = this.description.serialize();
|
|
240
315
|
return json;
|
|
241
316
|
}
|
|
242
317
|
|
|
@@ -11,7 +11,7 @@ import { arrayfromJSONorString, numberfromJSON } from '../util/JSONParse.ts';
|
|
|
11
11
|
*/
|
|
12
12
|
export class LocatorLocations {
|
|
13
13
|
/** Contains one or more fragment in the resource referenced by the `Locator`. */
|
|
14
|
-
public readonly fragments
|
|
14
|
+
public readonly fragments?: Array<string>;
|
|
15
15
|
|
|
16
16
|
/** Progression in the resource expressed as a percentage (between 0 and 1). */
|
|
17
17
|
public readonly progression?: number;
|
|
@@ -43,7 +43,7 @@ export class Manifest {
|
|
|
43
43
|
}) {
|
|
44
44
|
this.context = values.context;
|
|
45
45
|
this.metadata = values.metadata;
|
|
46
|
-
this.links = values.links;
|
|
46
|
+
this.links = values.links || new Links([]);
|
|
47
47
|
this.readingOrder = values.readingOrder;
|
|
48
48
|
this.resources = values.resources;
|
|
49
49
|
this.toc = values.toc;
|
|
@@ -63,8 +63,6 @@ export class Manifest {
|
|
|
63
63
|
|
|
64
64
|
if (!metadata) return;
|
|
65
65
|
|
|
66
|
-
const links = Links.deserialize(json.links);
|
|
67
|
-
|
|
68
66
|
const readingOrder = Links.deserialize(
|
|
69
67
|
json.readingOrder ? json.readingOrder : json.spine
|
|
70
68
|
);
|
|
@@ -80,7 +78,7 @@ export class Manifest {
|
|
|
80
78
|
return new Manifest({
|
|
81
79
|
context: arrayfromJSONorString(json['@context']),
|
|
82
80
|
metadata,
|
|
83
|
-
links,
|
|
81
|
+
links: Links.deserialize(json.links),
|
|
84
82
|
readingOrder,
|
|
85
83
|
resources: Links.deserialize(json.resources),
|
|
86
84
|
toc: Links.deserialize(json.toc),
|
|
@@ -95,7 +93,7 @@ export class Manifest {
|
|
|
95
93
|
const json: any = {};
|
|
96
94
|
if (this.context !== undefined) json['@context'] = this.context;
|
|
97
95
|
json.metadata = this.metadata.serialize();
|
|
98
|
-
if (this.links
|
|
96
|
+
if (this.links && this.links.items.length > 0) json.links = this.links.serialize();
|
|
99
97
|
json.readingOrder = this.readingOrder.serialize();
|
|
100
98
|
if (this.resources) json.resources = this.resources.serialize();
|
|
101
99
|
if (this.toc) json.toc = this.toc.serialize();
|
|
@@ -222,26 +220,33 @@ export class Manifest {
|
|
|
222
220
|
|
|
223
221
|
/** The URL where this publication is served, computed from the `Link` with `self` relation.
|
|
224
222
|
* e.g. https://provider.com/pub1293/manifest.json gives https://provider.com/pub1293/
|
|
223
|
+
*
|
|
224
|
+
* Drops the query, fragment and last path segment, so for any hierarchical
|
|
225
|
+
* URL the result ends in `/`. The frame CSP relies on this, since a source
|
|
226
|
+
* path only prefix-matches when it ends in a slash.
|
|
225
227
|
*/
|
|
226
228
|
public get baseURL(): string | undefined {
|
|
227
229
|
const selfLink = this.links?.items.find(
|
|
228
230
|
el => el.rels && el.rels.has('self')
|
|
229
231
|
);
|
|
230
|
-
if (selfLink)
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
232
|
+
if (!selfLink) return undefined;
|
|
233
|
+
|
|
234
|
+
const href = selfLink.href;
|
|
235
|
+
if (!href) return undefined;
|
|
236
|
+
|
|
237
|
+
try {
|
|
238
|
+
const url = new URL(href);
|
|
239
|
+
url.search = '';
|
|
240
|
+
url.hash = '';
|
|
241
|
+
url.pathname = url.pathname.substring(
|
|
242
|
+
0,
|
|
243
|
+
url.pathname.lastIndexOf('/') + 1
|
|
244
|
+
);
|
|
245
|
+
return url.href;
|
|
246
|
+
} catch {
|
|
247
|
+
// Relative self link (e.g. `/manifest.json`), not parseable by `URL`
|
|
248
|
+
return href.split(/[?#]/)[0].replace(/[^/]*$/, '');
|
|
243
249
|
}
|
|
244
|
-
return undefined;
|
|
245
250
|
}
|
|
246
251
|
|
|
247
252
|
/**
|
|
@@ -21,17 +21,13 @@ export function getDomRange(loc: LocatorLocations): DomRange | undefined {
|
|
|
21
21
|
// A WICG text-fragment directive (":~:text=...") found among fragments, per
|
|
22
22
|
// https://wicg.github.io/scroll-to-text-fragment/.
|
|
23
23
|
export function getTextFragment(loc: LocatorLocations): TextFragmentDirective | undefined {
|
|
24
|
-
|
|
25
|
-
const directive = decodeTextFragmentDirective(fragment);
|
|
26
|
-
if (directive) return directive;
|
|
27
|
-
}
|
|
28
|
-
return undefined;
|
|
24
|
+
return loc.fragments?.map(f => decodeTextFragmentDirective(f)).find(d => d);
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
export function getFragmentParameters(loc: LocatorLocations): Map<string, string> {
|
|
32
28
|
return new Map(
|
|
33
29
|
loc.fragments
|
|
34
|
-
|
|
30
|
+
?.map(f => f.startsWith('#') ? f.slice(1) : f)
|
|
35
31
|
.join('&')
|
|
36
32
|
.split('&')
|
|
37
33
|
.filter(f => !f.startsWith('#'))
|
|
@@ -46,7 +42,7 @@ export function getHtmlId(loc: LocatorLocations): string | undefined {
|
|
|
46
42
|
The HTML 5 specification (used for WebPub) allows any character in an HTML ID, except spaces.
|
|
47
43
|
This is an issue to differentiate with named parameters, so we ignore any ID containing `=`.
|
|
48
44
|
*/
|
|
49
|
-
if (!loc.fragments
|
|
45
|
+
if (!loc.fragments?.length) return;
|
|
50
46
|
let f = loc.fragments.find(f => f.length && !f.includes('='));
|
|
51
47
|
if (!f) {
|
|
52
48
|
const fp = getFragmentParameters(loc);
|
|
@@ -2,9 +2,13 @@ import { DefaultTextContentTokenizer, Range, TextTokenizer, TextUnit, Tokenizer
|
|
|
2
2
|
import { Locator, LocatorText } from "../../Locator.ts";
|
|
3
3
|
import { ContentElement, TextElement, TextSegment } from "./element/index.ts";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* A tokenizer splitting a [Content.Element] into smaller pieces.
|
|
7
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
8
|
+
*/
|
|
6
9
|
export type ContentTokenizer = Tokenizer<ContentElement, ContentElement>;
|
|
7
10
|
|
|
11
|
+
/** @deprecated Use `@readium/speech`, which segments text itself. */
|
|
8
12
|
export class TextContentTokenizer implements ContentTokenizer {
|
|
9
13
|
/**
|
|
10
14
|
*
|
|
@@ -21,6 +21,8 @@ interface ElementWithDelta {
|
|
|
21
21
|
* If you want to start from the end of the resource, the [locator] must have a `progression` of 1.0.
|
|
22
22
|
*
|
|
23
23
|
* Locators will contain a `before` context of up to `beforeMaxLength` characters.
|
|
24
|
+
*
|
|
25
|
+
* @deprecated Use `@readium/guided-navigation` and `@readium/speech` instead.
|
|
24
26
|
*/
|
|
25
27
|
export class HTMLResourceContentIterator extends Iterator {
|
|
26
28
|
private currentElement: ElementWithDelta | null = null;
|
|
@@ -107,6 +107,13 @@ export class MediaType {
|
|
|
107
107
|
return parts.length > 1 ? `+${parts[parts.length - 1]}` : undefined;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
/** The media type without its parameters, e.g. `text/html` for `text/html;charset=utf-8`.
|
|
111
|
+
* See. https://mimesniff.spec.whatwg.org/#mime-type-essence
|
|
112
|
+
*/
|
|
113
|
+
public get essence(): string {
|
|
114
|
+
return `${this.type}/${this.subtype}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
110
117
|
/** Parameter values might or might not be case-sensitive, depending on the semantics of
|
|
111
118
|
* the parameter name.
|
|
112
119
|
* https://tools.ietf.org/html/rfc2616#section-3.7
|
|
@@ -3,16 +3,21 @@ import { Tokenizer } from "./Tokenizer.ts";
|
|
|
3
3
|
import BasicEnglishTokenizer from "./tokenize-english/index.js";
|
|
4
4
|
import BasicTokenizer, { TextlintSegment } from "./tokenize-text/index.js";
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Start / End
|
|
8
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
9
|
+
*/
|
|
7
10
|
export type Range = [number, number];
|
|
8
11
|
|
|
9
12
|
/**
|
|
10
13
|
* A tokenizer splitting a String into range tokens (e.g. words, sentences, etc.).
|
|
14
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
11
15
|
*/
|
|
12
16
|
export type TextTokenizer = Tokenizer<string, Range>;
|
|
13
17
|
|
|
14
18
|
/**
|
|
15
19
|
* A text token unit which can be used with a [TextTokenizer].
|
|
20
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
16
21
|
*/
|
|
17
22
|
export enum TextUnit {
|
|
18
23
|
Word = "word",
|
|
@@ -20,7 +25,10 @@ export enum TextUnit {
|
|
|
20
25
|
Paragraph = "paragraph",
|
|
21
26
|
}
|
|
22
27
|
|
|
23
|
-
|
|
28
|
+
/**
|
|
29
|
+
* A default cluster [TextTokenizer] taking advantage of the best capabilities of the navigator
|
|
30
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
31
|
+
*/
|
|
24
32
|
export const DefaultTextContentTokenizer = (language: Language | null, unit: TextUnit): TextTokenizer => {
|
|
25
33
|
if("Segmenter" in Intl) {
|
|
26
34
|
// Available in any evergreen browser EXCEPT for Firefox.
|
|
@@ -35,6 +43,7 @@ export const DefaultTextContentTokenizer = (language: Language | null, unit: Tex
|
|
|
35
43
|
/**
|
|
36
44
|
* A [TextTokenizer] using the Intl.Segmenter API.
|
|
37
45
|
* Very aware of language-specific rules since it uses ICU behind the scenes.
|
|
46
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
38
47
|
*/
|
|
39
48
|
export class IntlTextTokenizer implements TextTokenizer {
|
|
40
49
|
private segmenter: Intl.Segmenter;
|
|
@@ -68,6 +77,7 @@ export class IntlTextTokenizer implements TextTokenizer {
|
|
|
68
77
|
* A [TextTokenizer] using a naive approach to splitting text into tokens.
|
|
69
78
|
* This is a fallback for browsers that don't support Intl.Segmenter.
|
|
70
79
|
* It works mainly on English and similar languages. Don't use unless necessary.
|
|
80
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
71
81
|
*/
|
|
72
82
|
export class NaiveTextTokenizer {
|
|
73
83
|
private tokenizer: BasicTokenizer;
|
|
@@ -116,8 +126,11 @@ export class NaiveTextTokenizer {
|
|
|
116
126
|
|
|
117
127
|
const trimmedMatcher = new RegExp("[\\p{L}\\p{N}]+", "u");
|
|
118
128
|
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Unicode-aware of checking if there's anything that can be spoken in a string
|
|
131
|
+
* "Spoken" in this case means at least one unicode letter or unicode number character
|
|
132
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
133
|
+
*/
|
|
121
134
|
export const speakableToken = (token: string): string | null => {
|
|
122
135
|
const trimmedToken = token.trimEnd();
|
|
123
136
|
if(trimmedToken.length === 0) return null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Link } from '../publication/Link.ts';
|
|
2
2
|
import { Fetcher } from './Fetcher.ts';
|
|
3
|
-
import { NumberRange, Resource } from './Resource.ts';
|
|
3
|
+
import { NumberRange, Resource, ResourceReadOptions } from './Resource.ts';
|
|
4
4
|
export type FetchImplementation = (input: RequestInfo | URL, init?: RequestInit | undefined) => Promise<Response>;
|
|
5
5
|
export declare class HttpFetcher implements Fetcher {
|
|
6
6
|
private readonly baseUrl?;
|
|
@@ -20,9 +20,9 @@ export declare class HttpResource implements Resource {
|
|
|
20
20
|
private headResponse;
|
|
21
21
|
close(): void;
|
|
22
22
|
link(): Promise<Link>;
|
|
23
|
-
read(range?: NumberRange): Promise<Uint8Array | undefined>;
|
|
23
|
+
read(range?: NumberRange, options?: ResourceReadOptions): Promise<Uint8Array | undefined>;
|
|
24
24
|
length(): Promise<number>;
|
|
25
25
|
readAsJSON(): Promise<unknown>;
|
|
26
26
|
readAsString(): Promise<string>;
|
|
27
|
-
readAsXML(): Promise<
|
|
27
|
+
readAsXML(): Promise<Document>;
|
|
28
28
|
}
|
|
@@ -4,12 +4,16 @@ export declare class NumberRange {
|
|
|
4
4
|
readonly endInclusive: number;
|
|
5
5
|
constructor(start: number, endInclusive: number);
|
|
6
6
|
}
|
|
7
|
+
export interface ResourceReadOptions {
|
|
8
|
+
/** Aborts the underlying request, e.g. when a prefetched resource is no longer needed */
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
7
11
|
export declare abstract class Resource {
|
|
8
12
|
abstract link(): Promise<Link>;
|
|
9
13
|
abstract length(): Promise<number | undefined>;
|
|
10
|
-
abstract read(range?: NumberRange): Promise<Uint8Array | undefined>;
|
|
14
|
+
abstract read(range?: NumberRange, options?: ResourceReadOptions): Promise<Uint8Array | undefined>;
|
|
11
15
|
readAsString(): Promise<string | undefined>;
|
|
12
16
|
readAsJSON(): Promise<unknown | undefined>;
|
|
13
|
-
readAsXML(): Promise<
|
|
17
|
+
readAsXML(): Promise<Document | undefined>;
|
|
14
18
|
abstract close(): void;
|
|
15
19
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { Links } from "./Link.ts";
|
|
2
1
|
export interface Clip {
|
|
3
2
|
audioResource: string;
|
|
4
3
|
fragmentId?: string;
|
|
@@ -10,17 +9,21 @@ export interface Clip {
|
|
|
10
9
|
* https://readium.org/guided-navigation/schema/document.schema.json
|
|
11
10
|
*/
|
|
12
11
|
export declare class GuidedNavigationDocument {
|
|
13
|
-
|
|
14
|
-
readonly guided
|
|
12
|
+
/** Non-empty sequence of objects meant to be presented sequentially to the user. */
|
|
13
|
+
readonly guided: GuidedNavigationObject[];
|
|
15
14
|
constructor(values: {
|
|
16
|
-
|
|
17
|
-
guided?: GuidedNavigationObject[];
|
|
15
|
+
guided: GuidedNavigationObject[];
|
|
18
16
|
});
|
|
17
|
+
/**
|
|
18
|
+
* Deserializes a GuidedNavigationDocument from JSON.
|
|
19
|
+
* Returns undefined if `guided` is missing or has no valid object.
|
|
20
|
+
*/
|
|
19
21
|
static deserialize(json: any): GuidedNavigationDocument | undefined;
|
|
20
22
|
serialize(): any;
|
|
21
23
|
}
|
|
22
24
|
/**
|
|
23
25
|
* Represents a text value containing plain text, SSML, and language information.
|
|
26
|
+
* https://readium.org/guided-navigation/schema/text.schema.json
|
|
24
27
|
*/
|
|
25
28
|
export declare class GuidedNavigationText {
|
|
26
29
|
/** Plain text content */
|
|
@@ -46,11 +49,42 @@ export declare class GuidedNavigationText {
|
|
|
46
49
|
*/
|
|
47
50
|
serialize(): any;
|
|
48
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Text, audio, image or video description of a Guided Navigation Object.
|
|
54
|
+
* https://readium.org/guided-navigation/schema/description.schema.json
|
|
55
|
+
*/
|
|
56
|
+
export declare class GuidedNavigationDescription {
|
|
57
|
+
/** References an audio resource or a fragment of it. */
|
|
58
|
+
readonly audioref?: string;
|
|
59
|
+
/** References an image or a fragment of it. */
|
|
60
|
+
readonly imgref?: string;
|
|
61
|
+
/** References a textual resource or a fragment of it. */
|
|
62
|
+
readonly textref?: string;
|
|
63
|
+
/** References a video resource or a fragment of it. */
|
|
64
|
+
readonly videoref?: string;
|
|
65
|
+
/** Textual description. */
|
|
66
|
+
readonly text?: GuidedNavigationText;
|
|
67
|
+
constructor(values: {
|
|
68
|
+
audioref?: string;
|
|
69
|
+
imgref?: string;
|
|
70
|
+
textref?: string;
|
|
71
|
+
videoref?: string;
|
|
72
|
+
text?: GuidedNavigationText;
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* Deserializes a GuidedNavigationDescription from JSON.
|
|
76
|
+
* Returns undefined if it has none of the refs nor text.
|
|
77
|
+
*/
|
|
78
|
+
static deserialize(json: any): GuidedNavigationDescription | undefined;
|
|
79
|
+
serialize(): any;
|
|
80
|
+
}
|
|
49
81
|
/**
|
|
50
82
|
* Guided Navigation Object
|
|
51
|
-
* https://
|
|
83
|
+
* https://readium.org/guided-navigation/schema/document.schema.json
|
|
52
84
|
*/
|
|
53
85
|
export declare class GuidedNavigationObject {
|
|
86
|
+
/** Identifier of the object. */
|
|
87
|
+
readonly id?: string;
|
|
54
88
|
/** References an audio resource or a fragment of it. */
|
|
55
89
|
readonly audioref?: string;
|
|
56
90
|
/** Items that are children of the containing Guided Navigation Object. */
|
|
@@ -59,35 +93,29 @@ export declare class GuidedNavigationObject {
|
|
|
59
93
|
readonly imgref?: string;
|
|
60
94
|
/** Convey the structural semantics of a publication. */
|
|
61
95
|
readonly role?: Set<string>;
|
|
62
|
-
/**
|
|
63
|
-
* Indicates the heading level (1-6) for the navigation object.
|
|
64
|
-
* @minimum 1
|
|
65
|
-
* @maximum 6
|
|
66
|
-
*/
|
|
67
|
-
readonly level?: number;
|
|
68
96
|
/**
|
|
69
97
|
* Textual equivalent of the resources or fragment of the resources referenced by the current Guided Navigation Object.
|
|
70
98
|
*/
|
|
71
99
|
readonly text?: GuidedNavigationText;
|
|
72
100
|
/** References a textual resource or a fragment of it. */
|
|
73
101
|
readonly textref?: string;
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
readonly description?: Omit<GuidedNavigationObject, 'level' | 'children'>;
|
|
102
|
+
/** References a video resource or a fragment of it. */
|
|
103
|
+
readonly videoref?: string;
|
|
104
|
+
/** Text, audio, image or video description of the current Guided Navigation Object. */
|
|
105
|
+
readonly description?: GuidedNavigationDescription;
|
|
79
106
|
/**
|
|
80
107
|
* Creates a [GuidedNavigation] object.
|
|
81
108
|
*/
|
|
82
109
|
constructor(values: {
|
|
110
|
+
id?: string;
|
|
83
111
|
audioref?: string;
|
|
84
112
|
children?: GuidedNavigationObject[];
|
|
85
113
|
imgref?: string;
|
|
86
114
|
role?: Set<string>;
|
|
87
|
-
level?: number;
|
|
88
115
|
text?: GuidedNavigationText;
|
|
89
116
|
textref?: string;
|
|
90
|
-
|
|
117
|
+
videoref?: string;
|
|
118
|
+
description?: GuidedNavigationDescription;
|
|
91
119
|
});
|
|
92
120
|
/**
|
|
93
121
|
* Gets the plain text content.
|
|
@@ -103,7 +131,8 @@ export declare class GuidedNavigationObject {
|
|
|
103
131
|
*/
|
|
104
132
|
get textLanguage(): string | undefined;
|
|
105
133
|
/**
|
|
106
|
-
* Deserializes a GuidedNavigationObject from JSON
|
|
134
|
+
* Deserializes a GuidedNavigationObject from JSON.
|
|
135
|
+
* Returns undefined if it has none of the refs, text, nor children.
|
|
107
136
|
*/
|
|
108
137
|
static deserialize(json: any): GuidedNavigationObject | undefined;
|
|
109
138
|
/**
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export declare class LocatorLocations {
|
|
6
6
|
/** Contains one or more fragment in the resource referenced by the `Locator`. */
|
|
7
|
-
readonly fragments
|
|
7
|
+
readonly fragments?: Array<string>;
|
|
8
8
|
/** Progression in the resource expressed as a percentage (between 0 and 1). */
|
|
9
9
|
readonly progression?: number;
|
|
10
10
|
/** Progression in the publication expressed as a percentage (between 0 and 1). */
|
|
@@ -50,6 +50,10 @@ export declare class Manifest {
|
|
|
50
50
|
linkWithHref(href: string): Link | undefined;
|
|
51
51
|
/** The URL where this publication is served, computed from the `Link` with `self` relation.
|
|
52
52
|
* e.g. https://provider.com/pub1293/manifest.json gives https://provider.com/pub1293/
|
|
53
|
+
*
|
|
54
|
+
* Drops the query, fragment and last path segment, so for any hierarchical
|
|
55
|
+
* URL the result ends in `/`. The frame CSP relies on this, since a source
|
|
56
|
+
* path only prefix-matches when it ends in a slash.
|
|
53
57
|
*/
|
|
54
58
|
get baseURL(): string | undefined;
|
|
55
59
|
/**
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { TextTokenizer, TextUnit, Tokenizer } from "../../../util/index.ts";
|
|
2
2
|
import { ContentElement } from "./element/index.ts";
|
|
3
|
+
/**
|
|
4
|
+
* A tokenizer splitting a [Content.Element] into smaller pieces.
|
|
5
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
6
|
+
*/
|
|
3
7
|
export type ContentTokenizer = Tokenizer<ContentElement, ContentElement>;
|
|
8
|
+
/** @deprecated Use `@readium/speech`, which segments text itself. */
|
|
4
9
|
export declare class TextContentTokenizer implements ContentTokenizer {
|
|
5
10
|
private readonly defaultLanguage;
|
|
6
11
|
private readonly contextSnippetLength;
|
|
@@ -11,6 +11,8 @@ import { ContentElement } from "../element/index.ts";
|
|
|
11
11
|
* If you want to start from the end of the resource, the [locator] must have a `progression` of 1.0.
|
|
12
12
|
*
|
|
13
13
|
* Locators will contain a `before` context of up to `beforeMaxLength` characters.
|
|
14
|
+
*
|
|
15
|
+
* @deprecated Use `@readium/guided-navigation` and `@readium/speech` instead.
|
|
14
16
|
*/
|
|
15
17
|
export declare class HTMLResourceContentIterator extends Iterator {
|
|
16
18
|
private resource;
|
|
@@ -37,6 +37,10 @@ export declare class MediaType {
|
|
|
37
37
|
* See. https://tools.ietf.org/html/rfc6838#section-4.2.8
|
|
38
38
|
*/
|
|
39
39
|
get structuredSyntaxSuffix(): string | undefined;
|
|
40
|
+
/** The media type without its parameters, e.g. `text/html` for `text/html;charset=utf-8`.
|
|
41
|
+
* See. https://mimesniff.spec.whatwg.org/#mime-type-essence
|
|
42
|
+
*/
|
|
43
|
+
get essence(): string;
|
|
40
44
|
/** Parameter values might or might not be case-sensitive, depending on the semantics of
|
|
41
45
|
* the parameter name.
|
|
42
46
|
* https://tools.ietf.org/html/rfc2616#section-3.7
|
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
import { Language } from "../Language.ts";
|
|
2
2
|
import { Tokenizer } from "./Tokenizer.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Start / End
|
|
5
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
6
|
+
*/
|
|
3
7
|
export type Range = [number, number];
|
|
4
8
|
/**
|
|
5
9
|
* A tokenizer splitting a String into range tokens (e.g. words, sentences, etc.).
|
|
10
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
6
11
|
*/
|
|
7
12
|
export type TextTokenizer = Tokenizer<string, Range>;
|
|
8
13
|
/**
|
|
9
14
|
* A text token unit which can be used with a [TextTokenizer].
|
|
15
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
10
16
|
*/
|
|
11
17
|
export declare enum TextUnit {
|
|
12
18
|
Word = "word",
|
|
13
19
|
Sentence = "sentence",
|
|
14
20
|
Paragraph = "paragraph"
|
|
15
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* A default cluster [TextTokenizer] taking advantage of the best capabilities of the navigator
|
|
24
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
25
|
+
*/
|
|
16
26
|
export declare const DefaultTextContentTokenizer: (language: Language | null, unit: TextUnit) => TextTokenizer;
|
|
17
27
|
/**
|
|
18
28
|
* A [TextTokenizer] using the Intl.Segmenter API.
|
|
19
29
|
* Very aware of language-specific rules since it uses ICU behind the scenes.
|
|
30
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
20
31
|
*/
|
|
21
32
|
export declare class IntlTextTokenizer implements TextTokenizer {
|
|
22
33
|
private unit;
|
|
@@ -28,6 +39,7 @@ export declare class IntlTextTokenizer implements TextTokenizer {
|
|
|
28
39
|
* A [TextTokenizer] using a naive approach to splitting text into tokens.
|
|
29
40
|
* This is a fallback for browsers that don't support Intl.Segmenter.
|
|
30
41
|
* It works mainly on English and similar languages. Don't use unless necessary.
|
|
42
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
31
43
|
*/
|
|
32
44
|
export declare class NaiveTextTokenizer {
|
|
33
45
|
private unit;
|
|
@@ -36,4 +48,9 @@ export declare class NaiveTextTokenizer {
|
|
|
36
48
|
constructor(language: Language | null, unit: TextUnit);
|
|
37
49
|
tokenize(data: string): Range[];
|
|
38
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Unicode-aware of checking if there's anything that can be spoken in a string
|
|
53
|
+
* "Spoken" in this case means at least one unicode letter or unicode number character
|
|
54
|
+
* @deprecated Use `@readium/speech`, which segments text itself.
|
|
55
|
+
*/
|
|
39
56
|
export declare const speakableToken: (token: string) => string | null;
|