@readium/shared 2.5.1 → 2.6.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
- class n{constructor(t,r){this.client=t||window.fetch.bind(window),this.baseUrl=r}links(){return[]}get(t){const r=t.toURL(this.baseUrl);if(r===void 0)throw Error(`Invalid HREF: ${t.href}`);return new i(this.client,t,r)}close(){}}class i{constructor(t,r,s){this.client=t||window.fetch.bind(window),this._link=r,this.url=s}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){if(t)throw new Error("http read range not implemented!");const r=await this.client(this.url);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 r=(await this.headResponse()).headers.get("content-length");if(r===null||r==="")throw new Error("length for resource unavailable");return parseInt(r)}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(),"application/xml")}}export{n as HttpFetcher,i as HttpResource};
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};
@@ -1 +1 @@
1
- class n{constructor(r,t){this.start=r,this.endInclusive=t}}class i{readAsString(){return this.read().then(r=>r===void 0?r:new TextDecoder().decode(r))}readAsJSON(){return this.readAsString().then(r=>r===void 0?r:JSON.parse(r))}readAsXML(){return this.readAsString().then(r=>r===void 0?r:new DOMParser().parseFromString(r,"text/xml"))}}export{n as NumberRange,i as Resource};
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};
@@ -1 +1 @@
1
- import{Metadata as k}from"./Metadata.js";import{Links as l,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,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=l.deserialize(e.links),r=l.deserialize(e.readingOrder?e.readingOrder:e.spine);if(!r)return;const s=new Set(["@context","metadata","links","readingOrder","spine","resources","toc"]),c={};return Object.keys(e).forEach(n=>{s.has(n)||(c[n]=e[n])}),new p({context:g(e["@context"]),metadata:i,links:t,readingOrder:r,resources:l.deserialize(e.resources),toc:l.deserialize(e.toc),subcollections:u.deserializeCollections(c)})}serialize(){const e={};return this.context!==void 0&&(e["@context"]=this.context),e.metadata=this.metadata.serialize(),this.links!==void 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=n=>{let o;for(const f of n)if(o=f.findWithHref(e),o!==void 0)return o;const h=new Array;return n.forEach(f=>{const d=[];for(const a of f.items)a.alternates&&d.push(a.alternates),a.children&&d.push(a.children);h.push(...d)}),h.length>0&&(o=i(h)),o},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 c=s[0];return this.linkWithHref(c)}get baseURL(){const e=this.links?.items.find(i=>i.rels&&i.rels.has("self"));if(e){let i=e.href;if(i){const t=i.lastIndexOf("/"),r=t===-1?void 0:i.substring(t+1);i=i.replace(new RegExp("/?$query$"),""),i=i.replace(new RegExp("//$"),""),r&&(i=i.replace(new RegExp(r+"$"),""))}return i}}setSelfLink(e){this.links||(this.links=new l([])),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
+ 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 C(e){return e.otherLocations?.get("cssSelector")}function L(e){return e.otherLocations?.get("partialCfi")}function N(e){return u.deserialize(e.otherLocations?.get("domRange"))}function W(e){for(const t of e.fragments){const r=d(t);if(r)return r}}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 F(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 R(e){const t=parseInt(n(e).get("page"));if(!isNaN(t)&&t>=0)return t}function T(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 a=r.toLowerCase();a.startsWith("pixel:")?s=r.slice(6):a.startsWith("percent:")&&(i="percent",s=r.slice(8));const c=i==="percent"?parseFloat:l=>parseInt(l,10),o=s.split(",").map(c);if(o.length!==4||o.some(isNaN))return;const[g,f,m,p]=o;return{unit:i,x:g,y:f,width:m,height:p}}export{C as getCssSelector,N as getDomRange,n as getFragmentParameters,F as getHtmlId,R as getPage,L as getPartialCfi,y as getSpace,W as getTextFragment,T as getTime};
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.5.1",
3
+ "version": "2.6.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.1.0"
59
+ "@readium/helpers": "1.1.1"
60
60
  },
61
61
  "files": [
62
62
  "dist",
@@ -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<XMLDocument> {
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
  }
@@ -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<XMLDocument | undefined> {
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
  }
@@ -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: Array<string>;
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 !== undefined) json.links = this.links.serialize();
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
- let href = selfLink.href;
232
- if (href) {
233
- const li = href.lastIndexOf('/');
234
- const lastpart = li === -1 ? undefined : href.substring(li + 1);
235
-
236
- href = href.replace(new RegExp('/?$query$'), '');
237
- href = href.replace(new RegExp('//$'), '');
238
- if (lastpart) {
239
- href = href.replace(new RegExp(lastpart + '$'), '');
240
- }
241
- }
242
- return href;
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
- for (const fragment of loc.fragments) {
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
- .map(f => f.startsWith('#') ? f.slice(1) : f)
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.length) return;
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);
@@ -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
@@ -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<XMLDocument>;
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<XMLDocument | undefined>;
17
+ readAsXML(): Promise<Document | undefined>;
14
18
  abstract close(): void;
15
19
  }
@@ -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: Array<string>;
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
  /**
@@ -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