storyblok-js-client
Advanced tools
Comparing version 5.8.0 to 5.9.0
@@ -1,1 +0,1 @@ | ||
(function(f,d){typeof exports=="object"&&typeof module<"u"?module.exports=d():typeof define=="function"&&define.amd?define(d):(f=typeof globalThis<"u"?globalThis:f||self,f.StoryblokJSClient=d())})(this,function(){"use strict";var S=Object.defineProperty;var C=(f,d,p)=>d in f?S(f,d,{enumerable:!0,configurable:!0,writable:!0,value:p}):f[d]=p;var h=(f,d,p)=>(C(f,typeof d!="symbol"?d+"":d,p),p);function f(a){return!(a!==a||a===1/0||a===-1/0)}function d(a,t,e){if(!f(t))throw new TypeError("Expected `limit` to be a finite number");if(!f(e))throw new TypeError("Expected `interval` to be a finite number");const s=[];let r=[],n=0;const i=function(){n++;const o=setTimeout(function(){n--,s.length>0&&i(),r=r.filter(function(u){return u!==o})},e);r.indexOf(o)<0&&r.push(o);const c=s.shift();c.resolve(a.apply(c.self,c.args))},l=function(...o){const c=this;return new Promise(function(u,y){s.push({resolve:u,reject:y,args:o,self:c}),n<t&&i()})};return l.abort=function(){r.forEach(clearTimeout),r=[],s.forEach(function(o){o.reject(function(){Error.call(this,"Throttled function aborted"),this.name="AbortError"})}),s.length=0},l}const p=function(a,t){const e={};for(const s in a){const r=a[s];t.indexOf(s)>-1&&r!==null&&(e[s]=r)}return e},P=a=>a==="email",R={nodes:{horizontal_rule:()=>({singleTag:"hr"}),blockquote:()=>({tag:"blockquote"}),bullet_list:()=>({tag:"ul"}),code_block:a=>({tag:["pre",{tag:"code",attrs:a.attrs}]}),hard_break:()=>({singleTag:"br"}),heading:a=>({tag:`h${a.attrs.level}`}),image:a=>({singleTag:[{tag:"img",attrs:p(a.attrs,["src","alt","title"])}]}),list_item:()=>({tag:"li"}),ordered_list:()=>({tag:"ol"}),paragraph:()=>({tag:"p"}),emoji:a=>({tag:[{tag:"span",attrs:{["data-type"]:"emoji",["data-name"]:a.attrs.name}}]})},marks:{bold:()=>({tag:"b"}),strike:()=>({tag:"strike"}),underline:()=>({tag:"u"}),strong:()=>({tag:"strong"}),code:()=>({tag:"code"}),italic:()=>({tag:"i"}),link:a=>{const t={...a.attrs},{linktype:e="url"}=a.attrs;if(P(e)&&(t.href=`mailto:${t.href}`),t.anchor&&(t.href=`${t.href}#${t.anchor}`,delete t.anchor),t.custom){for(const s in t.custom)t[s]=t.custom[s];delete t.custom}return{tag:[{tag:"a",attrs:t}]}},styled:a=>({tag:[{tag:"span",attrs:a.attrs}]}),subscript:()=>({tag:"sub"}),superscript:()=>({tag:"sup"}),anchor:a=>({tag:[{tag:"span",attrs:a.attrs}]}),highlight:a=>({tag:[{tag:"span",attrs:{style:`background-color:${a.attrs.color};`}}]}),textStyle:a=>({tag:[{tag:"span",attrs:{style:`background-color:${a.attrs.color}`}}]})}},$=function(a){const t={"&":"&","<":"<",">":">",'"':""","'":"'"},e=/[&<>"']/g,s=RegExp(e.source);return a&&s.test(a)?a.replace(e,r=>t[r]):a};class v{constructor(t){h(this,"marks");h(this,"nodes");t||(t=R),this.marks=t.marks||[],this.nodes=t.nodes||[]}addNode(t,e){this.nodes[t]=e}addMark(t,e){this.marks[t]=e}render(t,e={optimizeImages:!1}){if(t&&t.content&&Array.isArray(t.content)){let s="";return t.content.forEach(r=>{s+=this.renderNode(r)}),e.optimizeImages?s.replace(/a.storyblok.com\/f\/(\d+)\/([^.]+)\.(gif|jpg|jpeg|png|tif|tiff|bmp)/g,"a.storyblok.com/f/$1/$2.$3/m/"):s}return console.warn("The render method must receive an object with a content field, which is an array"),""}renderNode(t){const e=[];t.marks&&t.marks.forEach(r=>{const n=this.getMatchingMark(r);n&&e.push(this.renderOpeningTag(n.tag))});const s=this.getMatchingNode(t);return s&&s.tag&&e.push(this.renderOpeningTag(s.tag)),t.content?t.content.forEach(r=>{e.push(this.renderNode(r))}):t.text?e.push($(t.text)):s&&s.singleTag?e.push(this.renderTag(s.singleTag," /")):s&&s.html&&e.push(s.html),s&&s.tag&&e.push(this.renderClosingTag(s.tag)),t.marks&&t.marks.slice(0).reverse().forEach(r=>{const n=this.getMatchingMark(r);n&&e.push(this.renderClosingTag(n.tag))}),e.join("")}renderTag(t,e){return t.constructor===String?`<${t}${e}>`:t.map(r=>{if(r.constructor===String)return`<${r}${e}>`;{let n=`<${r.tag}`;if(r.attrs)for(const i in r.attrs){const l=r.attrs[i];l!==null&&(n+=` ${i}="${l}"`)}return`${n}${e}>`}}).join("")}renderOpeningTag(t){return this.renderTag(t,"")}renderClosingTag(t){return t.constructor===String?`</${t}>`:t.slice(0).reverse().map(s=>s.constructor===String?`</${s}>`:`</${s.tag}>`).join("")}getMatchingNode(t){const e=this.nodes[t.type];if(typeof e=="function")return e(t)}getMatchingMark(t){const e=this.marks[t.type];if(typeof e=="function")return e(t)}}class k{constructor(){h(this,"isCDNUrl",(t="")=>t.indexOf("/cdn/")>-1);h(this,"getOptionsPage",(t,e=25,s=1)=>({...t,per_page:e,page:s}));h(this,"delay",t=>new Promise(e=>setTimeout(e,t)));h(this,"arrayFrom",(t=0,e)=>[...Array(t)].map(e));h(this,"range",(t=0,e=t)=>{const s=Math.abs(e-t)||0,r=t<e?1:-1;return this.arrayFrom(s,(n,i)=>i*r+t)});h(this,"asyncMap",async(t,e)=>Promise.all(t.map(e)));h(this,"flatMap",(t=[],e)=>t.map(e).reduce((s,r)=>[...s,...r],[]))}stringify(t,e,s){const r=[];for(const n in t){if(!Object.prototype.hasOwnProperty.call(t,n))continue;const i=t[n],l=s?"":encodeURIComponent(n);let o;typeof i=="object"?o=this.stringify(i,e?e+encodeURIComponent("["+l+"]"):l,Array.isArray(i)):o=(e?e+encodeURIComponent("["+l+"]"):l)+"="+encodeURIComponent(i),r.push(o)}return r.join("&")}getRegionURL(t){const e="api.storyblok.com",s="api-us.storyblok.com",r="app.storyblokchina.cn";switch(t){case"us":return s;case"cn":return r;default:return e}}}const x=Object.freeze(Object.defineProperty({__proto__:null,SbHelpers:k},Symbol.toStringTag,{value:"Module"}));class T{constructor(t){h(this,"baseURL");h(this,"timeout");h(this,"headers");h(this,"responseInterceptor");h(this,"fetch");h(this,"ejectInterceptor");h(this,"url");h(this,"parameters");this.baseURL=t.baseURL,this.headers=t.headers||new Headers,this.timeout=t!=null&&t.timeout?t.timeout*1e3:0,this.responseInterceptor=t.responseInterceptor,this.fetch=(...e)=>t.fetch?t.fetch(...e):fetch(...e),this.ejectInterceptor=!1,this.url="",this.parameters={}}get(t,e){return this.url=t,this.parameters=e,this._methodHandler("get")}post(t,e){return this.url=t,this.parameters=e,this._methodHandler("post")}put(t,e){return this.url=t,this.parameters=e,this._methodHandler("put")}delete(t,e){return this.url=t,this.parameters=e,this._methodHandler("delete")}async _responseHandler(t){const e=[],s={data:{},headers:{},status:0,statusText:""};t.status!==204&&await t.json().then(r=>{s.data=r});for(const r of t.headers.entries())e[r[0]]=r[1];return s.headers={...e},s.status=t.status,s.statusText=t.statusText,s}async _methodHandler(t){let e=`${this.baseURL}${this.url}`,s=null;if(t==="get"){const o=new k;e=`${this.baseURL}${this.url}?${o.stringify(this.parameters)}`}else s=JSON.stringify(this.parameters);const r=new URL(e),n=new AbortController,{signal:i}=n;let l;this.timeout&&(l=setTimeout(()=>n.abort(),this.timeout));try{const o=await this.fetch(`${r}`,{method:t,headers:this.headers,body:s,signal:i});this.timeout&&clearTimeout(l);const c=await this._responseHandler(o);return this.responseInterceptor&&!this.ejectInterceptor?this._statusHandler(this.responseInterceptor(c)):this._statusHandler(c)}catch(o){return{message:o}}}eject(){this.ejectInterceptor=!0}_statusHandler(t){const e=/20[0-6]/g;return new Promise((s,r)=>{if(e.test(`${t.status}`))return s(t);const n={message:new Error(t.statusText),status:t.status,response:Array.isArray(t.data)?t.data[0]:t.data.error||t.data.slug};r(n)})}}let m={};const g={};class _{constructor(t,e){h(this,"client");h(this,"maxRetries");h(this,"throttle");h(this,"accessToken");h(this,"cache");h(this,"helpers");h(this,"resolveCounter");h(this,"relations");h(this,"links");h(this,"richTextResolver");h(this,"resolveNestedRelations");if(!e){const n=new k().getRegionURL,i=t.https===!1?"http":"https";t.oauthToken?e=`${i}://${n(t.region)}/v1`:e=`${i}://${n(t.region)}/v2`}const s=new Headers;s.set("Content-Type","application/json"),s.set("Accept","application/json"),s.forEach((n,i)=>{t.headers&&t.headers[i]&&s.set(i,t.headers[i])});let r=5;t.oauthToken&&(s.set("Authorization",t.oauthToken),r=3),t.rateLimit&&(r=t.rateLimit),t.richTextSchema?this.richTextResolver=new v(t.richTextSchema):this.richTextResolver=new v,t.componentResolver&&this.setComponentResolver(t.componentResolver),this.maxRetries=t.maxRetries,this.throttle=d(this.throttledRequest,r,1e3),this.accessToken=t.accessToken||"",this.relations={},this.links={},this.cache=t.cache||{clear:"manual"},this.helpers=new k,this.resolveCounter=0,this.resolveNestedRelations=!1,this.client=new T({baseURL:e,timeout:t.timeout||0,headers:s,responseInterceptor:t.responseInterceptor,fetch:t.fetch})}setComponentResolver(t){this.richTextResolver.addNode("blok",e=>{let s="";return e.attrs.body.forEach(r=>{s+=t(r.component,r)}),{html:s}})}parseParams(t){return t.version||(t.version="published"),t.token||(t.token=this.getToken()),t.cv||(t.cv=g[t.token]),Array.isArray(t.resolve_relations)&&(t.resolve_relations=t.resolve_relations.join(",")),t}factoryParamOptions(t,e){return this.helpers.isCDNUrl(t)?this.parseParams(e):e}makeRequest(t,e,s,r){const n=this.factoryParamOptions(t,this.helpers.getOptionsPage(e,s,r));return this.cacheResponse(t,n)}get(t,e){e||(e={});const s=`/${t}`,r=this.factoryParamOptions(s,e);return this.cacheResponse(s,r)}async getAll(t,e,s){const r=(e==null?void 0:e.per_page)||25,n=`/${t}`,i=n.split("/"),l=s||i[i.length-1],o=1,c=await this.makeRequest(n,e,r,o),u=c.total?Math.ceil(c.total/r):1,y=await this.helpers.asyncMap(this.helpers.range(o,u),b=>this.makeRequest(n,e,r,b+1));return this.helpers.flatMap([c,...y],b=>Object.values(b.data[l]))}post(t,e){const s=`/${t}`;return Promise.resolve(this.throttle("post",s,e))}put(t,e){const s=`/${t}`;return Promise.resolve(this.throttle("put",s,e))}delete(t,e){const s=`/${t}`;return Promise.resolve(this.throttle("delete",s,e))}getStories(t){return this.get("cdn/stories",t)}getStory(t,e){return this.get(`cdn/stories/${t}`,e)}getToken(){return this.accessToken}ejectInterceptor(){this.client.eject()}_cleanCopy(t){return JSON.parse(JSON.stringify(t))}_insertLinks(t,e,s){const r=t[e];r&&r.fieldtype=="multilink"&&r.linktype=="story"&&typeof r.id=="string"&&this.links[s][r.id]?r.story=this._cleanCopy(this.links[s][r.id]):r&&r.linktype==="story"&&typeof r.uuid=="string"&&this.links[s][r.uuid]&&(r.story=this._cleanCopy(this.links[s][r.uuid]))}_insertRelations(t,e,s,r){if(s.indexOf(`${t.component}.${e}`)>-1){if(typeof t[e]=="string")this.relations[r][t[e]]&&(t[e]=this._cleanCopy(this.relations[r][t[e]]));else if(t[e]&&t[e].constructor===Array){const n=[];t[e].forEach(i=>{this.relations[r][i]&&n.push(this._cleanCopy(this.relations[r][i]))}),t[e]=n}}}iterateTree(t,e,s){const r=n=>{if(n!=null){if(n.constructor===Array)for(let i=0;i<n.length;i++)r(n[i]);else if(n.constructor===Object){if(n._stopResolving)return;for(const i in n)(n.component&&n._uid||n.type==="link")&&(this._insertRelations(n,i,e,s),this._insertLinks(n,i,s)),r(n[i])}}};r(t.content)}async resolveLinks(t,e,s){let r=[];if(t.link_uuids){const n=t.link_uuids.length,i=[],l=50;for(let o=0;o<n;o+=l){const c=Math.min(n,o+l);i.push(t.link_uuids.slice(o,c))}for(let o=0;o<i.length;o++)(await this.getStories({per_page:l,language:e.language,version:e.version,by_uuids:i[o].join(",")})).data.stories.forEach(u=>{r.push(u)})}else r=t.links;r.forEach(n=>{this.links[s][n.uuid]={...n,_stopResolving:!0}})}async resolveRelations(t,e,s){let r=[];if(t.rel_uuids){const n=t.rel_uuids.length,i=[],l=50;for(let o=0;o<n;o+=l){const c=Math.min(n,o+l);i.push(t.rel_uuids.slice(o,c))}for(let o=0;o<i.length;o++)(await this.getStories({per_page:l,language:e.language,version:e.version,by_uuids:i[o].join(",")})).data.stories.forEach(u=>{r.push(u)})}else r=t.rels;r&&r.length>0&&r.forEach(n=>{this.relations[s][n.uuid]={...n,_stopResolving:!0}})}async resolveStories(t,e,s){var n,i;let r=[];if(this.links[s]={},this.relations[s]={},typeof e.resolve_relations<"u"&&e.resolve_relations.length>0&&(typeof e.resolve_relations=="string"&&(r=e.resolve_relations.split(",")),await this.resolveRelations(t,e,s)),e.resolve_links&&["1","story","url"].indexOf(e.resolve_links)>-1&&((n=t.links)!=null&&n.length||(i=t.link_uuids)!=null&&i.length)&&await this.resolveLinks(t,e,s),this.resolveNestedRelations)for(const l in this.relations[s])this.iterateTree(this.relations[s][l],r,s);t.story?this.iterateTree(t.story,r,s):t.stories.forEach(l=>{this.iterateTree(l,r,s)}),delete this.links[s],delete this.relations[s]}async cacheResponse(t,e,s){const r=this.helpers.stringify({url:t,params:e}),n=this.cacheProvider();if(this.cache.clear==="auto"&&e.version==="draft"&&await this.flushCache(),e.version==="published"&&t!="/cdn/spaces/me"){const i=await n.get(r);if(i)return Promise.resolve(i)}return new Promise((i,l)=>{try{(async()=>{var o;try{const c=await this.throttle("get",t,e);let u={data:c.data,headers:c.headers};if((o=c.headers)!=null&&o["per-page"]&&(u=Object.assign({},u,{perPage:c.headers["per-page"]?parseInt(c.headers["per-page"]):0,total:c.headers["per-page"]?parseInt(c.headers.total):0})),c.status!=200)return l(c);if(u.data.story||u.data.stories){const y=this.resolveCounter=++this.resolveCounter%1e3;await this.resolveStories(u.data,e,`${y}`)}return e.version==="published"&&t!="/cdn/spaces/me"&&await n.set(r,u),u.data.cv&&e.token&&(e.version=="draft"&&g[e.token]!=u.data.cv&&await this.flushCache(),g[e.token]=u.data.cv),i(u)}catch(c){return l(c)}})()}catch{}})}throttledRequest(t,e,s){return this.client[t](e,s)}cacheVersions(){return g}cacheVersion(){return g[this.accessToken]}setCacheVersion(t){this.accessToken&&(g[this.accessToken]=t)}cacheProvider(){switch(this.cache.type){case"memory":return{get(t){return Promise.resolve(m[t])},getAll(){return Promise.resolve(m)},set(t,e){return m[t]=e,Promise.resolve(void 0)},flush(){return m={},Promise.resolve(void 0)}};case"custom":if(this.cache.custom)return this.cache.custom;default:return{get(){return Promise.resolve(void 0)},getAll(){return Promise.resolve(void 0)},set(){return Promise.resolve(void 0)},flush(){return Promise.resolve(void 0)}}}}async flushCache(){return await this.cacheProvider().flush(),this}}const w=(a,t)=>{for(const e in t)a[e]=t[e]};return w(_,{RichtextResolver:v,SbFetch:T,RichTextSchema:R}),w(_,x),_}); | ||
(function(d,f){typeof exports=="object"&&typeof module<"u"?module.exports=f():typeof define=="function"&&define.amd?define(f):(d=typeof globalThis<"u"?globalThis:d||self,d.StoryblokJSClient=f())})(this,function(){"use strict";var O=Object.defineProperty;var U=(d,f,m)=>f in d?O(d,f,{enumerable:!0,configurable:!0,writable:!0,value:m}):d[f]=m;var h=(d,f,m)=>(U(d,typeof f!="symbol"?f+"":f,m),m);function d(a){return!(a!==a||a===1/0||a===-1/0)}function f(a,e,t){if(!d(e))throw new TypeError("Expected `limit` to be a finite number");if(!d(t))throw new TypeError("Expected `interval` to be a finite number");const s=[];let r=[],i=0;const n=function(){i++;const o=setTimeout(function(){i--,s.length>0&&n(),r=r.filter(function(u){return u!==o})},t);r.indexOf(o)<0&&r.push(o);const l=s.shift();l.resolve(a.apply(l.self,l.args))},c=function(...o){const l=this;return new Promise(function(u,p){s.push({resolve:u,reject:p,args:o,self:l}),i<e&&n()})};return c.abort=function(){r.forEach(clearTimeout),r=[],s.forEach(function(o){o.reject(function(){Error.call(this,"Throttled function aborted"),this.name="AbortError"})}),s.length=0},c}const m=function(a,e){const t={};for(const s in a){const r=a[s];e.indexOf(s)>-1&&r!==null&&(t[s]=r)}return t},C=a=>a==="email",w={nodes:{horizontal_rule:()=>({singleTag:"hr"}),blockquote:()=>({tag:"blockquote"}),bullet_list:()=>({tag:"ul"}),code_block:a=>({tag:["pre",{tag:"code",attrs:a.attrs}]}),hard_break:()=>({singleTag:"br"}),heading:a=>({tag:`h${a.attrs.level}`}),image:a=>({singleTag:[{tag:"img",attrs:m(a.attrs,["src","alt","title"])}]}),list_item:()=>({tag:"li"}),ordered_list:()=>({tag:"ol"}),paragraph:()=>({tag:"p"}),emoji:a=>({tag:[{tag:"span",attrs:{["data-type"]:"emoji",["data-name"]:a.attrs.name}}]})},marks:{bold:()=>({tag:"b"}),strike:()=>({tag:"strike"}),underline:()=>({tag:"u"}),strong:()=>({tag:"strong"}),code:()=>({tag:"code"}),italic:()=>({tag:"i"}),link:a=>{const e={...a.attrs},{linktype:t="url"}=a.attrs;if(C(t)&&(e.href=`mailto:${e.href}`),e.anchor&&(e.href=`${e.href}#${e.anchor}`,delete e.anchor),e.custom){for(const s in e.custom)e[s]=e.custom[s];delete e.custom}return{tag:[{tag:"a",attrs:e}]}},styled:a=>({tag:[{tag:"span",attrs:a.attrs}]}),subscript:()=>({tag:"sub"}),superscript:()=>({tag:"sup"}),anchor:a=>({tag:[{tag:"span",attrs:a.attrs}]}),highlight:a=>({tag:[{tag:"span",attrs:{style:`background-color:${a.attrs.color};`}}]}),textStyle:a=>({tag:[{tag:"span",attrs:{style:`background-color:${a.attrs.color}`}}]})}},A=function(a){const e={"&":"&","<":"<",">":">",'"':""","'":"'"},t=/[&<>"']/g,s=RegExp(t.source);return a&&s.test(a)?a.replace(t,r=>e[r]):a};class R{constructor(e){h(this,"marks");h(this,"nodes");e||(e=w),this.marks=e.marks||[],this.nodes=e.nodes||[]}addNode(e,t){this.nodes[e]=t}addMark(e,t){this.marks[e]=t}render(e,t={optimizeImages:!1}){if(e&&e.content&&Array.isArray(e.content)){let s="";return e.content.forEach(r=>{s+=this.renderNode(r)}),t.optimizeImages?this.optimizeImages(s,t.optimizeImages):s}return console.warn("The render method must receive an object with a content field, which is an array"),""}optimizeImages(e,t){let s=0,r=0,i="",n="";typeof t!="boolean"&&(typeof t.width=="number"&&t.width>0&&(i+=`width="${t.width}" `,s=t.width),typeof t.height=="number"&&t.height>0&&(i+=`height="${t.height}" `,r=t.height),(t.loading==="lazy"||t.loading==="eager")&&(i+=`loading="${t.loading}" `),typeof t.class=="string"&&t.class.length>0&&(i+=`class="${t.class}" `),t.filters&&(typeof t.filters.blur=="number"&&t.filters.blur>=0&&t.filters.blur<=100&&(n+=`:blur(${t.filters.blur})`),typeof t.filters.brightness=="number"&&t.filters.brightness>=-100&&t.filters.brightness<=100&&(n+=`:brightness(${t.filters.brightness})`),t.filters.fill&&(t.filters.fill.match(/[0-9A-Fa-f]{6}/g)||t.filters.fill==="transparent")&&(n+=`:fill(${t.filters.fill})`),t.filters.format&&["webp","png","jpeg"].includes(t.filters.format)&&(n+=`:format(${t.filters.format})`),typeof t.filters.grayscale=="boolean"&&t.filters.grayscale&&(n+=":grayscale()"),typeof t.filters.quality=="number"&&t.filters.quality>=0&&t.filters.quality<=100&&(n+=`:quality(${t.filters.quality})`),t.filters.rotate&&[90,180,270].includes(t.filters.rotate)&&(n+=`:rotate(${t.filters.rotate})`),n.length>0&&(n="/filters"+n))),i.length>0&&(e=e.replace(/<img/g,`<img ${i.trim()}`));const c=s>0||r>0||n.length>0?`${s}x${r}${n}`:"";return e=e.replace(/a.storyblok.com\/f\/(\d+)\/([^.]+)\.(gif|jpg|jpeg|png|tif|tiff|bmp)/g,`a.storyblok.com/f/$1/$2.$3/m/${c}`),typeof t!="boolean"&&(t.sizes||t.srcset)&&(e=e.replace(/<img.*?src=["|'](.*?)["|']/g,o=>{var u,p;const l=o.match(/a.storyblok.com\/f\/(\d+)\/([^.]+)\.(gif|jpg|jpeg|png|tif|tiff|bmp)/g);if(l&&l.length>0){const y={srcset:(u=t.srcset)==null?void 0:u.map(g=>{if(typeof g=="number")return`//${l}/m/${g}x0${n} ${g}w`;if(typeof g=="object"&&g.length===2){let T=0,S=0;return typeof g[0]=="number"&&(T=g[0]),typeof g[1]=="number"&&(S=g[1]),`//${l}/m/${T}x${S}${n} ${T}w`}}).join(", "),sizes:(p=t.sizes)==null?void 0:p.map(g=>g).join(", ")};let v="";return y.srcset&&(v+=`srcset="${y.srcset}" `),y.sizes&&(v+=`sizes="${y.sizes}" `),o.replace(/<img/g,`<img ${v.trim()}`)}return o})),e}renderNode(e){const t=[];e.marks&&e.marks.forEach(r=>{const i=this.getMatchingMark(r);i&&t.push(this.renderOpeningTag(i.tag))});const s=this.getMatchingNode(e);return s&&s.tag&&t.push(this.renderOpeningTag(s.tag)),e.content?e.content.forEach(r=>{t.push(this.renderNode(r))}):e.text?t.push(A(e.text)):s&&s.singleTag?t.push(this.renderTag(s.singleTag," /")):s&&s.html&&t.push(s.html),s&&s.tag&&t.push(this.renderClosingTag(s.tag)),e.marks&&e.marks.slice(0).reverse().forEach(r=>{const i=this.getMatchingMark(r);i&&t.push(this.renderClosingTag(i.tag))}),t.join("")}renderTag(e,t){return e.constructor===String?`<${e}${t}>`:e.map(r=>{if(r.constructor===String)return`<${r}${t}>`;{let i=`<${r.tag}`;if(r.attrs)for(const n in r.attrs){const c=r.attrs[n];c!==null&&(i+=` ${n}="${c}"`)}return`${i}${t}>`}}).join("")}renderOpeningTag(e){return this.renderTag(e,"")}renderClosingTag(e){return e.constructor===String?`</${e}>`:e.slice(0).reverse().map(s=>s.constructor===String?`</${s}>`:`</${s.tag}>`).join("")}getMatchingNode(e){const t=this.nodes[e.type];if(typeof t=="function")return t(e)}getMatchingMark(e){const t=this.marks[e.type];if(typeof t=="function")return t(e)}}class b{constructor(){h(this,"isCDNUrl",(e="")=>e.indexOf("/cdn/")>-1);h(this,"getOptionsPage",(e,t=25,s=1)=>({...e,per_page:t,page:s}));h(this,"delay",e=>new Promise(t=>setTimeout(t,e)));h(this,"arrayFrom",(e=0,t)=>[...Array(e)].map(t));h(this,"range",(e=0,t=e)=>{const s=Math.abs(t-e)||0,r=e<t?1:-1;return this.arrayFrom(s,(i,n)=>n*r+e)});h(this,"asyncMap",async(e,t)=>Promise.all(e.map(t)));h(this,"flatMap",(e=[],t)=>e.map(t).reduce((s,r)=>[...s,...r],[]))}stringify(e,t,s){const r=[];for(const i in e){if(!Object.prototype.hasOwnProperty.call(e,i))continue;const n=e[i],c=s?"":encodeURIComponent(i);let o;typeof n=="object"?o=this.stringify(n,t?t+encodeURIComponent("["+c+"]"):c,Array.isArray(n)):o=(t?t+encodeURIComponent("["+c+"]"):c)+"="+encodeURIComponent(n),r.push(o)}return r.join("&")}getRegionURL(e){const t="api.storyblok.com",s="api-us.storyblok.com",r="app.storyblokchina.cn";switch(e){case"us":return s;case"cn":return r;default:return t}}}const E=Object.freeze(Object.defineProperty({__proto__:null,SbHelpers:b},Symbol.toStringTag,{value:"Module"}));class P{constructor(e){h(this,"baseURL");h(this,"timeout");h(this,"headers");h(this,"responseInterceptor");h(this,"fetch");h(this,"ejectInterceptor");h(this,"url");h(this,"parameters");this.baseURL=e.baseURL,this.headers=e.headers||new Headers,this.timeout=e!=null&&e.timeout?e.timeout*1e3:0,this.responseInterceptor=e.responseInterceptor,this.fetch=(...t)=>e.fetch?e.fetch(...t):fetch(...t),this.ejectInterceptor=!1,this.url="",this.parameters={}}get(e,t){return this.url=e,this.parameters=t,this._methodHandler("get")}post(e,t){return this.url=e,this.parameters=t,this._methodHandler("post")}put(e,t){return this.url=e,this.parameters=t,this._methodHandler("put")}delete(e,t){return this.url=e,this.parameters=t,this._methodHandler("delete")}async _responseHandler(e){const t=[],s={data:{},headers:{},status:0,statusText:""};e.status!==204&&await e.json().then(r=>{s.data=r});for(const r of e.headers.entries())t[r[0]]=r[1];return s.headers={...t},s.status=e.status,s.statusText=e.statusText,s}async _methodHandler(e){let t=`${this.baseURL}${this.url}`,s=null;if(e==="get"){const o=new b;t=`${this.baseURL}${this.url}?${o.stringify(this.parameters)}`}else s=JSON.stringify(this.parameters);const r=new URL(t),i=new AbortController,{signal:n}=i;let c;this.timeout&&(c=setTimeout(()=>i.abort(),this.timeout));try{const o=await this.fetch(`${r}`,{method:e,headers:this.headers,body:s,signal:n});this.timeout&&clearTimeout(c);const l=await this._responseHandler(o);return this.responseInterceptor&&!this.ejectInterceptor?this._statusHandler(this.responseInterceptor(l)):this._statusHandler(l)}catch(o){return{message:o}}}eject(){this.ejectInterceptor=!0}_statusHandler(e){const t=/20[0-6]/g;return new Promise((s,r)=>{if(t.test(`${e.status}`))return s(e);const i={message:new Error(e.statusText),status:e.status,response:Array.isArray(e.data)?e.data[0]:e.data.error||e.data.slug};r(i)})}}let _={};const k={};class ${constructor(e,t){h(this,"client");h(this,"maxRetries");h(this,"throttle");h(this,"accessToken");h(this,"cache");h(this,"helpers");h(this,"resolveCounter");h(this,"relations");h(this,"links");h(this,"richTextResolver");h(this,"resolveNestedRelations");if(!t){const i=new b().getRegionURL,n=e.https===!1?"http":"https";e.oauthToken?t=`${n}://${i(e.region)}/v1`:t=`${n}://${i(e.region)}/v2`}const s=new Headers;s.set("Content-Type","application/json"),s.set("Accept","application/json"),s.forEach((i,n)=>{e.headers&&e.headers[n]&&s.set(n,e.headers[n])});let r=5;e.oauthToken&&(s.set("Authorization",e.oauthToken),r=3),e.rateLimit&&(r=e.rateLimit),e.richTextSchema?this.richTextResolver=new R(e.richTextSchema):this.richTextResolver=new R,e.componentResolver&&this.setComponentResolver(e.componentResolver),this.maxRetries=e.maxRetries,this.throttle=f(this.throttledRequest,r,1e3),this.accessToken=e.accessToken||"",this.relations={},this.links={},this.cache=e.cache||{clear:"manual"},this.helpers=new b,this.resolveCounter=0,this.resolveNestedRelations=e.resolveNestedRelations||!0,this.client=new P({baseURL:t,timeout:e.timeout||0,headers:s,responseInterceptor:e.responseInterceptor,fetch:e.fetch})}setComponentResolver(e){this.richTextResolver.addNode("blok",t=>{let s="";return t.attrs.body.forEach(r=>{s+=e(r.component,r)}),{html:s}})}parseParams(e){return e.version||(e.version="published"),e.token||(e.token=this.getToken()),e.cv||(e.cv=k[e.token]),Array.isArray(e.resolve_relations)&&(e.resolve_relations=e.resolve_relations.join(",")),e}factoryParamOptions(e,t){return this.helpers.isCDNUrl(e)?this.parseParams(t):t}makeRequest(e,t,s,r){const i=this.factoryParamOptions(e,this.helpers.getOptionsPage(t,s,r));return this.cacheResponse(e,i)}get(e,t){t||(t={});const s=`/${e}`,r=this.factoryParamOptions(s,t);return this.cacheResponse(s,r)}async getAll(e,t,s){const r=(t==null?void 0:t.per_page)||25,i=`/${e}`,n=i.split("/"),c=s||n[n.length-1],o=1,l=await this.makeRequest(i,t,r,o),u=l.total?Math.ceil(l.total/r):1,p=await this.helpers.asyncMap(this.helpers.range(o,u),y=>this.makeRequest(i,t,r,y+1));return this.helpers.flatMap([l,...p],y=>Object.values(y.data[c]))}post(e,t){const s=`/${e}`;return Promise.resolve(this.throttle("post",s,t))}put(e,t){const s=`/${e}`;return Promise.resolve(this.throttle("put",s,t))}delete(e,t){const s=`/${e}`;return Promise.resolve(this.throttle("delete",s,t))}getStories(e){return this.get("cdn/stories",e)}getStory(e,t){return this.get(`cdn/stories/${e}`,t)}getToken(){return this.accessToken}ejectInterceptor(){this.client.eject()}_cleanCopy(e){return JSON.parse(JSON.stringify(e))}_insertLinks(e,t,s){const r=e[t];r&&r.fieldtype=="multilink"&&r.linktype=="story"&&typeof r.id=="string"&&this.links[s][r.id]?r.story=this._cleanCopy(this.links[s][r.id]):r&&r.linktype==="story"&&typeof r.uuid=="string"&&this.links[s][r.uuid]&&(r.story=this._cleanCopy(this.links[s][r.uuid]))}_insertRelations(e,t,s,r){if(s.indexOf(`${e.component}.${t}`)>-1){if(typeof e[t]=="string")this.relations[r][e[t]]&&(e[t]=this._cleanCopy(this.relations[r][e[t]]));else if(e[t]&&e[t].constructor===Array){const i=[];e[t].forEach(n=>{this.relations[r][n]&&i.push(this._cleanCopy(this.relations[r][n]))}),e[t]=i}}}iterateTree(e,t,s){const r=i=>{if(i!=null){if(i.constructor===Array)for(let n=0;n<i.length;n++)r(i[n]);else if(i.constructor===Object){if(i._stopResolving)return;for(const n in i)(i.component&&i._uid||i.type==="link")&&(this._insertRelations(i,n,t,s),this._insertLinks(i,n,s)),r(i[n])}}};r(e.content)}async resolveLinks(e,t,s){let r=[];if(e.link_uuids){const i=e.link_uuids.length,n=[],c=50;for(let o=0;o<i;o+=c){const l=Math.min(i,o+c);n.push(e.link_uuids.slice(o,l))}for(let o=0;o<n.length;o++)(await this.getStories({per_page:c,language:t.language,version:t.version,by_uuids:n[o].join(",")})).data.stories.forEach(u=>{r.push(u)})}else r=e.links;r.forEach(i=>{this.links[s][i.uuid]={...i,_stopResolving:!0}})}async resolveRelations(e,t,s){let r=[];if(e.rel_uuids){const i=e.rel_uuids.length,n=[],c=50;for(let o=0;o<i;o+=c){const l=Math.min(i,o+c);n.push(e.rel_uuids.slice(o,l))}for(let o=0;o<n.length;o++)(await this.getStories({per_page:c,language:t.language,version:t.version,by_uuids:n[o].join(",")})).data.stories.forEach(u=>{r.push(u)})}else r=e.rels;r&&r.length>0&&r.forEach(i=>{this.relations[s][i.uuid]={...i,_stopResolving:!0}})}async resolveStories(e,t,s){var i,n;let r=[];if(this.links[s]={},this.relations[s]={},typeof t.resolve_relations<"u"&&t.resolve_relations.length>0&&(typeof t.resolve_relations=="string"&&(r=t.resolve_relations.split(",")),await this.resolveRelations(e,t,s)),t.resolve_links&&["1","story","url"].indexOf(t.resolve_links)>-1&&((i=e.links)!=null&&i.length||(n=e.link_uuids)!=null&&n.length)&&await this.resolveLinks(e,t,s),this.resolveNestedRelations)for(const c in this.relations[s])this.iterateTree(this.relations[s][c],r,s);e.story?this.iterateTree(e.story,r,s):e.stories.forEach(c=>{this.iterateTree(c,r,s)}),delete this.links[s],delete this.relations[s]}async cacheResponse(e,t,s){const r=this.helpers.stringify({url:e,params:t}),i=this.cacheProvider();if(this.cache.clear==="auto"&&t.version==="draft"&&await this.flushCache(),t.version==="published"&&e!="/cdn/spaces/me"){const n=await i.get(r);if(n)return Promise.resolve(n)}return new Promise((n,c)=>{try{(async()=>{var o;try{const l=await this.throttle("get",e,t);let u={data:l.data,headers:l.headers};if((o=l.headers)!=null&&o["per-page"]&&(u=Object.assign({},u,{perPage:l.headers["per-page"]?parseInt(l.headers["per-page"]):0,total:l.headers["per-page"]?parseInt(l.headers.total):0})),l.status!=200)return c(l);if(u.data.story||u.data.stories){const p=this.resolveCounter=++this.resolveCounter%1e3;await this.resolveStories(u.data,t,`${p}`)}return t.version==="published"&&e!="/cdn/spaces/me"&&await i.set(r,u),u.data.cv&&t.token&&(t.version=="draft"&&k[t.token]!=u.data.cv&&await this.flushCache(),k[t.token]=u.data.cv),n(u)}catch(l){return c(l)}})()}catch{}})}throttledRequest(e,t,s){return this.client[e](t,s)}cacheVersions(){return k}cacheVersion(){return k[this.accessToken]}setCacheVersion(e){this.accessToken&&(k[this.accessToken]=e)}cacheProvider(){switch(this.cache.type){case"memory":return{get(e){return Promise.resolve(_[e])},getAll(){return Promise.resolve(_)},set(e,t){return _[e]=t,Promise.resolve(void 0)},flush(){return _={},Promise.resolve(void 0)}};case"custom":if(this.cache.custom)return this.cache.custom;default:return{get(){return Promise.resolve(void 0)},getAll(){return Promise.resolve(void 0)},set(){return Promise.resolve(void 0)},flush(){return Promise.resolve(void 0)}}}}async flushCache(){return await this.cacheProvider().flush(),this}}const x=(a,e)=>{for(const t in e)a[t]=e[t]};return x($,{RichtextResolver:R,SbFetch:P,RichTextSchema:w}),x($,E),$}); |
@@ -1,1 +0,1 @@ | ||
(function(a,o){typeof exports=="object"&&typeof module<"u"?module.exports=o():typeof define=="function"&&define.amd?define(o):(a=typeof globalThis<"u"?globalThis:a||self,a.RichTextResolver=o())})(this,function(){"use strict";var p=Object.defineProperty;var m=(a,o,c)=>o in a?p(a,o,{enumerable:!0,configurable:!0,writable:!0,value:c}):a[o]=c;var l=(a,o,c)=>(m(a,typeof o!="symbol"?o+"":o,c),c);const a=function(n,t){const e={};for(const r in n){const s=n[r];t.indexOf(r)>-1&&s!==null&&(e[r]=s)}return e},o=n=>n==="email",h={nodes:{horizontal_rule:()=>({singleTag:"hr"}),blockquote:()=>({tag:"blockquote"}),bullet_list:()=>({tag:"ul"}),code_block:n=>({tag:["pre",{tag:"code",attrs:n.attrs}]}),hard_break:()=>({singleTag:"br"}),heading:n=>({tag:`h${n.attrs.level}`}),image:n=>({singleTag:[{tag:"img",attrs:a(n.attrs,["src","alt","title"])}]}),list_item:()=>({tag:"li"}),ordered_list:()=>({tag:"ol"}),paragraph:()=>({tag:"p"}),emoji:n=>({tag:[{tag:"span",attrs:{["data-type"]:"emoji",["data-name"]:n.attrs.name}}]})},marks:{bold:()=>({tag:"b"}),strike:()=>({tag:"strike"}),underline:()=>({tag:"u"}),strong:()=>({tag:"strong"}),code:()=>({tag:"code"}),italic:()=>({tag:"i"}),link:n=>{const t={...n.attrs},{linktype:e="url"}=n.attrs;if(o(e)&&(t.href=`mailto:${t.href}`),t.anchor&&(t.href=`${t.href}#${t.anchor}`,delete t.anchor),t.custom){for(const r in t.custom)t[r]=t.custom[r];delete t.custom}return{tag:[{tag:"a",attrs:t}]}},styled:n=>({tag:[{tag:"span",attrs:n.attrs}]}),subscript:()=>({tag:"sub"}),superscript:()=>({tag:"sup"}),anchor:n=>({tag:[{tag:"span",attrs:n.attrs}]}),highlight:n=>({tag:[{tag:"span",attrs:{style:`background-color:${n.attrs.color};`}}]}),textStyle:n=>({tag:[{tag:"span",attrs:{style:`background-color:${n.attrs.color}`}}]})}},d=function(n){const t={"&":"&","<":"<",">":">",'"':""","'":"'"},e=/[&<>"']/g,r=RegExp(e.source);return n&&r.test(n)?n.replace(e,s=>t[s]):n};class f{constructor(t){l(this,"marks");l(this,"nodes");t||(t=h),this.marks=t.marks||[],this.nodes=t.nodes||[]}addNode(t,e){this.nodes[t]=e}addMark(t,e){this.marks[t]=e}render(t,e={optimizeImages:!1}){if(t&&t.content&&Array.isArray(t.content)){let r="";return t.content.forEach(s=>{r+=this.renderNode(s)}),e.optimizeImages?r.replace(/a.storyblok.com\/f\/(\d+)\/([^.]+)\.(gif|jpg|jpeg|png|tif|tiff|bmp)/g,"a.storyblok.com/f/$1/$2.$3/m/"):r}return console.warn("The render method must receive an object with a content field, which is an array"),""}renderNode(t){const e=[];t.marks&&t.marks.forEach(s=>{const i=this.getMatchingMark(s);i&&e.push(this.renderOpeningTag(i.tag))});const r=this.getMatchingNode(t);return r&&r.tag&&e.push(this.renderOpeningTag(r.tag)),t.content?t.content.forEach(s=>{e.push(this.renderNode(s))}):t.text?e.push(d(t.text)):r&&r.singleTag?e.push(this.renderTag(r.singleTag," /")):r&&r.html&&e.push(r.html),r&&r.tag&&e.push(this.renderClosingTag(r.tag)),t.marks&&t.marks.slice(0).reverse().forEach(s=>{const i=this.getMatchingMark(s);i&&e.push(this.renderClosingTag(i.tag))}),e.join("")}renderTag(t,e){return t.constructor===String?`<${t}${e}>`:t.map(s=>{if(s.constructor===String)return`<${s}${e}>`;{let i=`<${s.tag}`;if(s.attrs)for(const u in s.attrs){const g=s.attrs[u];g!==null&&(i+=` ${u}="${g}"`)}return`${i}${e}>`}}).join("")}renderOpeningTag(t){return this.renderTag(t,"")}renderClosingTag(t){return t.constructor===String?`</${t}>`:t.slice(0).reverse().map(r=>r.constructor===String?`</${r}>`:`</${r.tag}>`).join("")}getMatchingNode(t){const e=this.nodes[t.type];if(typeof e=="function")return e(t)}getMatchingMark(t){const e=this.marks[t.type];if(typeof e=="function")return e(t)}}return f}); | ||
(function(c,l){typeof exports=="object"&&typeof module<"u"?module.exports=l():typeof define=="function"&&define.amd?define(l):(c=typeof globalThis<"u"?globalThis:c||self,c.RichTextResolver=l())})(this,function(){"use strict";var w=Object.defineProperty;var x=(c,l,g)=>l in c?w(c,l,{enumerable:!0,configurable:!0,writable:!0,value:g}):c[l]=g;var $=(c,l,g)=>(x(c,typeof l!="symbol"?l+"":l,g),g);const c=function(s,e){const t={};for(const r in s){const n=s[r];e.indexOf(r)>-1&&n!==null&&(t[r]=n)}return t},l=s=>s==="email",T={nodes:{horizontal_rule:()=>({singleTag:"hr"}),blockquote:()=>({tag:"blockquote"}),bullet_list:()=>({tag:"ul"}),code_block:s=>({tag:["pre",{tag:"code",attrs:s.attrs}]}),hard_break:()=>({singleTag:"br"}),heading:s=>({tag:`h${s.attrs.level}`}),image:s=>({singleTag:[{tag:"img",attrs:c(s.attrs,["src","alt","title"])}]}),list_item:()=>({tag:"li"}),ordered_list:()=>({tag:"ol"}),paragraph:()=>({tag:"p"}),emoji:s=>({tag:[{tag:"span",attrs:{["data-type"]:"emoji",["data-name"]:s.attrs.name}}]})},marks:{bold:()=>({tag:"b"}),strike:()=>({tag:"strike"}),underline:()=>({tag:"u"}),strong:()=>({tag:"strong"}),code:()=>({tag:"code"}),italic:()=>({tag:"i"}),link:s=>{const e={...s.attrs},{linktype:t="url"}=s.attrs;if(l(t)&&(e.href=`mailto:${e.href}`),e.anchor&&(e.href=`${e.href}#${e.anchor}`,delete e.anchor),e.custom){for(const r in e.custom)e[r]=e.custom[r];delete e.custom}return{tag:[{tag:"a",attrs:e}]}},styled:s=>({tag:[{tag:"span",attrs:s.attrs}]}),subscript:()=>({tag:"sub"}),superscript:()=>({tag:"sup"}),anchor:s=>({tag:[{tag:"span",attrs:s.attrs}]}),highlight:s=>({tag:[{tag:"span",attrs:{style:`background-color:${s.attrs.color};`}}]}),textStyle:s=>({tag:[{tag:"span",attrs:{style:`background-color:${s.attrs.color}`}}]})}},j=function(s){const e={"&":"&","<":"<",">":">",'"':""","'":"'"},t=/[&<>"']/g,r=RegExp(t.source);return s&&r.test(s)?s.replace(t,n=>e[n]):s};class z{constructor(e){$(this,"marks");$(this,"nodes");e||(e=T),this.marks=e.marks||[],this.nodes=e.nodes||[]}addNode(e,t){this.nodes[e]=t}addMark(e,t){this.marks[e]=t}render(e,t={optimizeImages:!1}){if(e&&e.content&&Array.isArray(e.content)){let r="";return e.content.forEach(n=>{r+=this.renderNode(n)}),t.optimizeImages?this.optimizeImages(r,t.optimizeImages):r}return console.warn("The render method must receive an object with a content field, which is an array"),""}optimizeImages(e,t){let r=0,n=0,a="",i="";typeof t!="boolean"&&(typeof t.width=="number"&&t.width>0&&(a+=`width="${t.width}" `,r=t.width),typeof t.height=="number"&&t.height>0&&(a+=`height="${t.height}" `,n=t.height),(t.loading==="lazy"||t.loading==="eager")&&(a+=`loading="${t.loading}" `),typeof t.class=="string"&&t.class.length>0&&(a+=`class="${t.class}" `),t.filters&&(typeof t.filters.blur=="number"&&t.filters.blur>=0&&t.filters.blur<=100&&(i+=`:blur(${t.filters.blur})`),typeof t.filters.brightness=="number"&&t.filters.brightness>=-100&&t.filters.brightness<=100&&(i+=`:brightness(${t.filters.brightness})`),t.filters.fill&&(t.filters.fill.match(/[0-9A-Fa-f]{6}/g)||t.filters.fill==="transparent")&&(i+=`:fill(${t.filters.fill})`),t.filters.format&&["webp","png","jpeg"].includes(t.filters.format)&&(i+=`:format(${t.filters.format})`),typeof t.filters.grayscale=="boolean"&&t.filters.grayscale&&(i+=":grayscale()"),typeof t.filters.quality=="number"&&t.filters.quality>=0&&t.filters.quality<=100&&(i+=`:quality(${t.filters.quality})`),t.filters.rotate&&[90,180,270].includes(t.filters.rotate)&&(i+=`:rotate(${t.filters.rotate})`),i.length>0&&(i="/filters"+i))),a.length>0&&(e=e.replace(/<img/g,`<img ${a.trim()}`));const o=r>0||n>0||i.length>0?`${r}x${n}${i}`:"";return e=e.replace(/a.storyblok.com\/f\/(\d+)\/([^.]+)\.(gif|jpg|jpeg|png|tif|tiff|bmp)/g,`a.storyblok.com/f/$1/$2.$3/m/${o}`),typeof t!="boolean"&&(t.sizes||t.srcset)&&(e=e.replace(/<img.*?src=["|'](.*?)["|']/g,d=>{var y,p;const u=d.match(/a.storyblok.com\/f\/(\d+)\/([^.]+)\.(gif|jpg|jpeg|png|tif|tiff|bmp)/g);if(u&&u.length>0){const h={srcset:(y=t.srcset)==null?void 0:y.map(f=>{if(typeof f=="number")return`//${u}/m/${f}x0${i} ${f}w`;if(typeof f=="object"&&f.length===2){let b=0,k=0;return typeof f[0]=="number"&&(b=f[0]),typeof f[1]=="number"&&(k=f[1]),`//${u}/m/${b}x${k}${i} ${b}w`}}).join(", "),sizes:(p=t.sizes)==null?void 0:p.map(f=>f).join(", ")};let m="";return h.srcset&&(m+=`srcset="${h.srcset}" `),h.sizes&&(m+=`sizes="${h.sizes}" `),d.replace(/<img/g,`<img ${m.trim()}`)}return d})),e}renderNode(e){const t=[];e.marks&&e.marks.forEach(n=>{const a=this.getMatchingMark(n);a&&t.push(this.renderOpeningTag(a.tag))});const r=this.getMatchingNode(e);return r&&r.tag&&t.push(this.renderOpeningTag(r.tag)),e.content?e.content.forEach(n=>{t.push(this.renderNode(n))}):e.text?t.push(j(e.text)):r&&r.singleTag?t.push(this.renderTag(r.singleTag," /")):r&&r.html&&t.push(r.html),r&&r.tag&&t.push(this.renderClosingTag(r.tag)),e.marks&&e.marks.slice(0).reverse().forEach(n=>{const a=this.getMatchingMark(n);a&&t.push(this.renderClosingTag(a.tag))}),t.join("")}renderTag(e,t){return e.constructor===String?`<${e}${t}>`:e.map(n=>{if(n.constructor===String)return`<${n}${t}>`;{let a=`<${n.tag}`;if(n.attrs)for(const i in n.attrs){const o=n.attrs[i];o!==null&&(a+=` ${i}="${o}"`)}return`${a}${t}>`}}).join("")}renderOpeningTag(e){return this.renderTag(e,"")}renderClosingTag(e){return e.constructor===String?`</${e}>`:e.slice(0).reverse().map(r=>r.constructor===String?`</${r}>`:`</${r.tag}>`).join("")}getMatchingNode(e){const t=this.nodes[e.type];if(typeof t=="function")return t(e)}getMatchingMark(e){const t=this.marks[e.type];if(typeof t=="function")return t(e)}}return z}); |
import { ISbSchema, ISbRichtext } from './interfaces'; | ||
type OptimizeImagesOptions = boolean | { | ||
class?: string; | ||
filters?: { | ||
blur?: number; | ||
brightness?: number; | ||
fill?: string; | ||
format?: 'webp' | 'jpeg' | 'png'; | ||
grayscale?: boolean; | ||
quality?: number; | ||
rotate?: 90 | 180 | 270; | ||
}; | ||
height?: number; | ||
loading?: 'lazy' | 'eager'; | ||
sizes?: string[]; | ||
srcset?: (number | [number, number])[]; | ||
width?: number; | ||
}; | ||
type RenderOptions = { | ||
optimizeImages: boolean; | ||
optimizeImages?: OptimizeImagesOptions; | ||
}; | ||
@@ -12,2 +29,3 @@ declare class RichTextResolver { | ||
render(data?: ISbRichtext, options?: RenderOptions): string; | ||
private optimizeImages; | ||
private renderNode; | ||
@@ -14,0 +32,0 @@ private renderTag; |
{ | ||
"name": "storyblok-js-client", | ||
"version": "5.8.0", | ||
"version": "5.9.0", | ||
"description": "Universal JavaScript SDK for Storyblok's API", | ||
@@ -62,3 +62,3 @@ "license": "MIT", | ||
"prettier": "^2.7.1", | ||
"typescript": "^4.8.4", | ||
"typescript": "^5.0.2", | ||
"vite": "^4.0.4", | ||
@@ -65,0 +65,0 @@ "vitest": "^0.29.1" |
@@ -143,2 +143,3 @@ <div align="center"> | ||
- (`richTextSchema` Object, optional - your custom schema for RichTextRenderer) | ||
- (`resolveNestedRelations` Boolean, optional - By default is true) | ||
- (`endpoint` String, optional) | ||
@@ -385,2 +386,3 @@ | ||
- `data` Richtext object, An object with a `content` (an array of nodes) field. | ||
- `options` (optional) Options to control render behavior. | ||
@@ -393,2 +395,52 @@ **Example** | ||
**Optimizing images** | ||
You can instruct the richtext resolver to optimize images using [Storyblok Image Service](https://www.storyblok.com/docs/image-service) | ||
passing the option `optimizeImages: true`. | ||
**Example** | ||
```javascript | ||
Storyblok.richTextResolver.render(blok.richtext, { optimizeImages: true }) | ||
``` | ||
Also, it is possible to customize this option passing an object. | ||
All properties are optional and will be applied to each image in the field. | ||
**Example** | ||
```js | ||
const options = { | ||
optimizeImages: { | ||
class: 'w-full my-8 border-b border-black', | ||
width: 640, // image width | ||
height: 360, // image height | ||
loading: 'lazy', // 'lazy' | 'eager' | ||
filters: { | ||
blur: 0, // 0 to 100 | ||
brightness: 0, // -100 to 100 | ||
fill: 'transparent', // Or any hexadecimal value like FFCC99 | ||
format: 'webp', // 'webp' | 'jpeg' | 'png' | ||
grayscale: false, | ||
quality: 95, // 0 to 100 | ||
rotate: 0 // 0 | 90 | 180 | 270 | ||
}, | ||
// srcset accepts an array with image widths. | ||
// Example: [720, 1024, 1533] | ||
// will render srcset="//../m/720x0 720w", "//../m/1024x0 1024w", "//../m/1533x0 1280w" | ||
// Also accept an array to pass width and height. | ||
// Example: [[720,500], 1024, [1500, 1000]] | ||
// will render srcset="//../m/720x500 720w", "//../m/1024x0 1024w", "//../m/1280x0 1280w" | ||
srcset: [720, 1024, 1533], | ||
sizes: [ | ||
'(max-width: 767px) 100vw', | ||
'(max-width: 1024px) 768px', | ||
'1500px' | ||
] | ||
} | ||
} | ||
Storyblok.richTextResolver.render(blok.richtext, options) | ||
``` | ||
### Code examples | ||
@@ -395,0 +447,0 @@ |
@@ -135,3 +135,3 @@ import throttledQueue from './throttlePromise' | ||
this.resolveCounter = 0 | ||
this.resolveNestedRelations = false | ||
this.resolveNestedRelations = config.resolveNestedRelations || true | ||
@@ -138,0 +138,0 @@ this.client = new SbFetch({ |
@@ -8,4 +8,24 @@ import defaultHtmlSerializer from './schema' | ||
type RenderOptions = { | ||
optimizeImages: boolean | ||
type OptimizeImagesOptions = | ||
| boolean | ||
| { | ||
class?: string | ||
filters?: { | ||
blur?: number | ||
brightness?: number | ||
fill?: string | ||
format?: 'webp' | 'jpeg' | 'png' | ||
grayscale?: boolean | ||
quality?: number | ||
rotate?: 90 | 180 | 270 | ||
} | ||
height?: number | ||
loading?: 'lazy' | 'eager' | ||
sizes?: string[] | ||
srcset?: (number | [number, number])[] | ||
width?: number | ||
} | ||
type RenderOptions = { | ||
optimizeImages?: OptimizeImagesOptions | ||
} | ||
@@ -59,3 +79,6 @@ | ||
public render(data?: ISbRichtext, options: RenderOptions = { optimizeImages: false } ) { | ||
public render( | ||
data?: ISbRichtext, | ||
options: RenderOptions = { optimizeImages: false } | ||
) { | ||
if (data && data.content && Array.isArray(data.content)) { | ||
@@ -68,4 +91,5 @@ let html = '' | ||
if (options.optimizeImages) | ||
return html.replace(/a.storyblok.com\/f\/(\d+)\/([^.]+)\.(gif|jpg|jpeg|png|tif|tiff|bmp)/g, "a.storyblok.com/f/$1/$2.$3/m/") | ||
if (options.optimizeImages) { | ||
return this.optimizeImages(html, options.optimizeImages) | ||
} | ||
@@ -81,2 +105,141 @@ return html | ||
private optimizeImages(html: string, options: OptimizeImagesOptions): string { | ||
let w = 0 | ||
let h = 0 | ||
let imageAttributes = '' | ||
let filters = '' | ||
if (typeof options !== 'boolean') { | ||
if (typeof options.width === 'number' && options.width > 0) { | ||
imageAttributes += `width="${options.width}" ` | ||
w = options.width | ||
} | ||
if (typeof options.height === 'number' && options.height > 0) { | ||
imageAttributes += `height="${options.height}" ` | ||
h = options.height | ||
} | ||
if (options.loading === 'lazy' || options.loading === 'eager') { | ||
imageAttributes += `loading="${options.loading}" ` | ||
} | ||
if (typeof options.class === 'string' && options.class.length > 0) { | ||
imageAttributes += `class="${options.class}" ` | ||
} | ||
if (options.filters) { | ||
if ( | ||
typeof options.filters.blur === 'number' && | ||
options.filters.blur >= 0 && | ||
options.filters.blur <= 100 | ||
) { | ||
filters += `:blur(${options.filters.blur})` | ||
} | ||
if ( | ||
typeof options.filters.brightness === 'number' && | ||
options.filters.brightness >= -100 && | ||
options.filters.brightness <= 100 | ||
) { | ||
filters += `:brightness(${options.filters.brightness})` | ||
} | ||
if ( | ||
options.filters.fill && | ||
(options.filters.fill.match(/[0-9A-Fa-f]{6}/g) || | ||
options.filters.fill === 'transparent') | ||
) { | ||
filters += `:fill(${options.filters.fill})` | ||
} | ||
if ( | ||
options.filters.format && | ||
['webp', 'png', 'jpeg'].includes(options.filters.format) | ||
) { | ||
filters += `:format(${options.filters.format})` | ||
} | ||
if ( | ||
typeof options.filters.grayscale === 'boolean' && | ||
options.filters.grayscale | ||
) { | ||
filters += ':grayscale()' | ||
} | ||
if ( | ||
typeof options.filters.quality === 'number' && | ||
options.filters.quality >= 0 && | ||
options.filters.quality <= 100 | ||
) { | ||
filters += `:quality(${options.filters.quality})` | ||
} | ||
if ( | ||
options.filters.rotate && | ||
[90, 180, 270].includes(options.filters.rotate) | ||
) { | ||
filters += `:rotate(${options.filters.rotate})` | ||
} | ||
if (filters.length > 0) filters = '/filters' + filters | ||
} | ||
} | ||
if (imageAttributes.length > 0) { | ||
html = html.replace(/<img/g, `<img ${imageAttributes.trim()}`) | ||
} | ||
const parameters = | ||
w > 0 || h > 0 || filters.length > 0 ? `${w}x${h}${filters}` : '' | ||
html = html.replace( | ||
/a.storyblok.com\/f\/(\d+)\/([^.]+)\.(gif|jpg|jpeg|png|tif|tiff|bmp)/g, | ||
`a.storyblok.com/f/$1/$2.$3/m/${parameters}` | ||
) | ||
if (typeof options !== 'boolean' && (options.sizes || options.srcset)) { | ||
html = html.replace(/<img.*?src=["|'](.*?)["|']/g, (value: string) => { | ||
const url = value.match( | ||
/a.storyblok.com\/f\/(\d+)\/([^.]+)\.(gif|jpg|jpeg|png|tif|tiff|bmp)/g | ||
) | ||
if (url && url.length > 0) { | ||
const imageAttributes = { | ||
srcset: options.srcset | ||
?.map((value) => { | ||
if (typeof value === 'number') { | ||
return `//${url}/m/${value}x0${filters} ${value}w` | ||
} | ||
if (typeof value === 'object' && value.length === 2) { | ||
let w = 0 | ||
let h = 0 | ||
if (typeof value[0] === 'number') w = value[0] | ||
if (typeof value[1] === 'number') h = value[1] | ||
return `//${url}/m/${w}x${h}${filters} ${w}w` | ||
} | ||
}) | ||
.join(', '), | ||
sizes: options.sizes?.map((size) => size).join(', '), | ||
} | ||
let renderImageAttributes = '' | ||
if (imageAttributes.srcset) { | ||
renderImageAttributes += `srcset="${imageAttributes.srcset}" ` | ||
} | ||
if (imageAttributes.sizes) { | ||
renderImageAttributes += `sizes="${imageAttributes.sizes}" ` | ||
} | ||
return value.replace(/<img/g, `<img ${renderImageAttributes.trim()}`) | ||
} | ||
return value | ||
}) | ||
} | ||
return html | ||
} | ||
private renderNode(item: ISbRichtext) { | ||
@@ -83,0 +246,0 @@ const html = [] |
@@ -78,16 +78,143 @@ /* eslint-disable no-undef */ | ||
const docWithImage = { | ||
type: 'doc', | ||
content: [ | ||
{ | ||
type: 'image', | ||
attrs: { | ||
src: 'https://a.storyblok.com/f/000000/00a00a00a0/image-name.png', | ||
}, | ||
}, | ||
], | ||
} | ||
test('image to generate img tag with optimization', () => { | ||
const doc = { | ||
type: 'doc', | ||
content: [ | ||
{ | ||
type: 'image', | ||
attrs: { | ||
src: 'https://a.storyblok.com/f/000000/00a00a00a0/image-name.png', | ||
}, | ||
expect(resolver.render(docWithImage, { optimizeImages: true })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
}) | ||
test('image to generate img tag with optimization and loading lazy', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { loading: 'lazy' } })) | ||
.toBe('<img loading="lazy" src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
}) | ||
test('image to generate img tag with optimization and width', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { width: 500 } })) | ||
.toBe('<img width="500" src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/500x0" />') | ||
}) | ||
test('image to generate img tag with optimization and height', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { height: 350 } })) | ||
.toBe('<img height="350" src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x350" />') | ||
}) | ||
test('image to generate img tag with optimization and custom class', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { class: 'w-full my-8' } })) | ||
.toBe('<img class="w-full my-8" src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { class: '' } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
}) | ||
test('image to generate img tag with optimization and filter blur', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { blur: 10 } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:blur(10)" />') | ||
}) | ||
test('image to generate img tag with optimization and filter brightness', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { brightness: 15 } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:brightness(15)" />') | ||
}) | ||
test('image to generate img tag with optimization and filter fill', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { fill: 'transparent' } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:fill(transparent)" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { fill: 'FFCC99' } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:fill(FFCC99)" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { fill: 'INVALID' } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
}) | ||
test('image to generate img tag with optimization and filter format', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { format: 'png' } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:format(png)" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { format: 'webp' } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:format(webp)" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { format: 'jpeg' } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:format(jpeg)" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { format: 'invalidFormat' } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
}) | ||
test('image to generate img tag with optimization and filter grayscale', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { grayscale: true } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:grayscale()" />') | ||
}) | ||
test('image to generate img tag with optimization and filter quality', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { quality: 90 } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:quality(90)" />') | ||
}) | ||
test('image to generate img tag with optimization and filter rotate', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { rotate: 90 } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:rotate(90)" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { rotate: 180 } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:rotate(180)" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { rotate: 270 } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/0x0/filters:rotate(270)" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { filters: { rotate: 9999 } } })) | ||
.toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
}) | ||
test('image to generate img tag with optimization and srcset', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { srcset: [360, 1024, 1500] } })) | ||
.toBe('<img srcset="//a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/360x0 360w, //a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/1024x0 1024w, //a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/1500x0 1500w" src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
expect(resolver.render(docWithImage, { optimizeImages: { srcset: [[360,360], 1024, 1500] } })) | ||
.toBe('<img srcset="//a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/360x360 360w, //a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/1024x0 1024w, //a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/1500x0 1500w" src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
}) | ||
test('image to generate img tag with optimization and sizes', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { sizes: ['(max-width: 767px) 100vw', '(max-width: 1024px) 768px', '1500px'] } })) | ||
.toBe('<img sizes="(max-width: 767px) 100vw, (max-width: 1024px) 768px, 1500px" src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
}) | ||
test('image to generate img tag with optimization and srcset and sizes', () => { | ||
expect(resolver.render(docWithImage, { optimizeImages: { srcset: [360, 1024, 1500], sizes: ['(max-width: 767px) 100vw', '(max-width: 1024px) 768px', '1500px'] } })) | ||
.toBe('<img srcset="//a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/360x0 360w, //a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/1024x0 1024w, //a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/1500x0 1500w" sizes="(max-width: 767px) 100vw, (max-width: 1024px) 768px, 1500px" src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
}) | ||
test('image to generate img tag with optimization and multiple options', () => { | ||
const options = { | ||
optimizeImages: { | ||
loading: 'lazy', | ||
class: 'w-full', | ||
width: 640, | ||
height: 360, | ||
filters: { | ||
blur: 1, | ||
brightness: 5, | ||
fill: 'transparent', | ||
format: 'webp', | ||
grayscale: true, | ||
quality: 95, | ||
rotate: 180 | ||
}, | ||
], | ||
srcset: [360, 1024, 1500], | ||
sizes: [ | ||
'(max-width: 767px) 100vw', | ||
'(max-width: 1024px) 768px', | ||
'1500px' | ||
] | ||
} | ||
} | ||
expect(resolver.render(doc, { optimizeImages: true })).toBe('<img src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/" />') | ||
expect(resolver.render(docWithImage, options)) | ||
.toBe('<img srcset="//a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/360x0/filters:blur(1):brightness(5):fill(transparent):format(webp):grayscale():quality(95):rotate(180) 360w, //a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/1024x0/filters:blur(1):brightness(5):fill(transparent):format(webp):grayscale():quality(95):rotate(180) 1024w, //a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/1500x0/filters:blur(1):brightness(5):fill(transparent):format(webp):grayscale():quality(95):rotate(180) 1500w" sizes="(max-width: 767px) 100vw, (max-width: 1024px) 768px, 1500px" width="640" height="360" loading="lazy" class="w-full" src="https://a.storyblok.com/f/000000/00a00a00a0/image-name.png/m/640x360/filters:blur(1):brightness(5):fill(transparent):format(webp):grayscale():quality(95):rotate(180)" />') | ||
}) | ||
@@ -94,0 +221,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
179704
4855
670