@storyblok/js 1.6.5 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
package/README.md CHANGED
@@ -190,6 +190,16 @@ sbBridge.on(["input", "published", "change"], (event) => {
190
190
  });
191
191
  ```
192
192
 
193
+ #### Rendering Rich Text
194
+
195
+ You can easily render rich text by using the `renderRichText` function that comes with `@storyblok/js`:
196
+
197
+ ```js
198
+ import { renderRichText } from "@storyblok/js";
199
+
200
+ const renderedRichText = renderRichText(blok.richtext);
201
+ ```
202
+
193
203
  ## 🔗 Related Links
194
204
 
195
205
  - **[Storyblok Technology Hub](https://www.storyblok.com/technologies?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-js)**: Storyblok integrates with every framework so that you are free to choose the best fit for your project. We prepared the technology hub so that you can find selected beginner tutorials, videos, boilerplates, and even cheatsheets all in one place.
@@ -1,5 +1,7 @@
1
- (function(u,d){typeof exports=="object"&&typeof module!="undefined"?d(exports,require("axios")):typeof define=="function"&&define.amd?define(["exports","axios"],d):(u=typeof globalThis!="undefined"?globalThis:u||self,d(u.storyblok={},u.e))})(this,function(u,d){"use strict";var z=Object.defineProperty,U=Object.defineProperties;var D=Object.getOwnPropertyDescriptors;var $=Object.getOwnPropertySymbols;var J=Object.prototype.hasOwnProperty,V=Object.prototype.propertyIsEnumerable;var S=(u,d,p)=>d in u?z(u,d,{enumerable:!0,configurable:!0,writable:!0,value:p}):u[d]=p,g=(u,d)=>{for(var p in d||(d={}))J.call(d,p)&&S(u,p,d[p]);if($)for(var p of $(d))V.call(d,p)&&S(u,p,d[p]);return u},k=(u,d)=>U(u,D(d));function p(n){return n&&typeof n=="object"&&"default"in n?n:{default:n}}var j=p(d);let v=!1;const w=[],T=n=>new Promise((t,s)=>{if(typeof window=="undefined"||(window.storyblokRegisterEvent=r=>{if(window.location===window.parent.location){console.warn("You are not in Draft Mode or in the Visual Editor.");return}v?r():w.push(r)},document.getElementById("storyblok-javascript-bridge")))return;const e=document.createElement("script");e.async=!0,e.src=n,e.id="storyblok-javascript-bridge",e.onerror=r=>s(r),e.onload=r=>{w.forEach(o=>o()),v=!0,t(r)},document.getElementsByTagName("head")[0].appendChild(e)});/*!
1
+ (function(h,d){typeof exports=="object"&&typeof module!="undefined"?d(exports,require("axios")):typeof define=="function"&&define.amd?define(["exports","axios"],d):(h=typeof globalThis!="undefined"?globalThis:h||self,d(h.storyblok={},h.e))})(this,function(h,d){"use strict";var Y=Object.defineProperty,G=Object.defineProperties;var K=Object.getOwnPropertyDescriptors;var E=Object.getOwnPropertySymbols;var Q=Object.prototype.hasOwnProperty,W=Object.prototype.propertyIsEnumerable;var j=(h,d,g)=>d in h?Y(h,d,{enumerable:!0,configurable:!0,writable:!0,value:g}):h[d]=g,p=(h,d)=>{for(var g in d||(d={}))Q.call(d,g)&&j(h,g,d[g]);if(E)for(var g of E(d))W.call(d,g)&&j(h,g,d[g]);return h},m=(h,d)=>G(h,K(d));function g(n){return n&&typeof n=="object"&&"default"in n?n:{default:n}}var S=g(d);let v=!1;const T=[],w=n=>new Promise((t,e)=>{if(typeof window=="undefined"||(window.storyblokRegisterEvent=s=>{if(window.location===window.parent.location){console.warn("You are not in Draft Mode or in the Visual Editor.");return}v?s():T.push(s)},document.getElementById("storyblok-javascript-bridge")))return;const r=document.createElement("script");r.async=!0,r.src=n,r.id="storyblok-javascript-bridge",r.onerror=s=>e(s),r.onload=s=>{T.forEach(o=>o()),v=!0,t(s)},document.getElementsByTagName("head")[0].appendChild(r)}),O=function(n,t){if(!n)return null;let e={};for(let r in n){let s=n[r];t.indexOf(r)>-1&&s!==null&&(e[r]=s)}return e},M=n=>n==="email";var A={nodes:{horizontal_rule(){return{singleTag:"hr"}},blockquote(){return{tag:"blockquote"}},bullet_list(){return{tag:"ul"}},code_block(n){return{tag:["pre",{tag:"code",attrs:n.attrs}]}},hard_break(){return{singleTag:"br"}},heading(n){return{tag:`h${n.attrs.level}`}},image(n){return{singleTag:[{tag:"img",attrs:O(n.attrs,["src","alt","title"])}]}},list_item(){return{tag:"li"}},ordered_list(){return{tag:"ol"}},paragraph(){return{tag:"p"}}},marks:{bold(){return{tag:"b"}},strike(){return{tag:"strike"}},underline(){return{tag:"u"}},strong(){return{tag:"strong"}},code(){return{tag:"code"}},italic(){return{tag:"i"}},link(n){const t=p({},n.attrs),{linktype:e="url"}=n.attrs;return M(e)&&(t.href=`mailto:${t.href}`),t.anchor&&(t.href=`${t.href}#${t.anchor}`,delete t.anchor),{tag:[{tag:"a",attrs:t}]}},styled(n){return{tag:[{tag:"span",attrs:n.attrs}]}}}};const x=function(n){const t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},e=/[&<>"']/g,r=RegExp(e.source);return n&&r.test(n)?n.replace(e,s=>t[s]):n};class C{constructor(t){t||(t=A),this.marks=t.marks||[],this.nodes=t.nodes||[]}addNode(t,e){this.nodes[t]=e}addMark(t,e){this.marks[t]=e}render(t={}){if(t.content&&Array.isArray(t.content)){let e="";return t.content.forEach(r=>{e+=this.renderNode(r)}),e}return console.warn("The render method must receive an object with a content field, which is an array"),""}renderNode(t){let e=[];t.marks&&t.marks.forEach(s=>{const o=this.getMatchingMark(s);o&&e.push(this.renderOpeningTag(o.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(x(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 o=this.getMatchingMark(s);o&&e.push(this.renderClosingTag(o.tag))}),e.join("")}renderTag(t,e){return t.constructor===String?`<${t}${e}>`:t.map(s=>{if(s.constructor===String)return`<${s}${e}>`;{let o=`<${s.tag}`;if(s.attrs)for(let i in s.attrs){let a=s.attrs[i];a!==null&&(o+=` ${i}="${a}"`)}return`${o}${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){if(typeof this.nodes[t.type]=="function")return this.nodes[t.type](t)}getMatchingMark(t){if(typeof this.marks[t.type]=="function")return this.marks[t.type](t)}}/*!
2
2
  * storyblok-js-client v4.5.2
3
3
  * Universal JavaScript SDK for Storyblok's API
4
4
  * (c) 2020-2022 Stobylok Team
5
- */function _(n){return typeof n=="number"&&n==n&&n!==1/0&&n!==-1/0}function R(n,t,s){if(!_(t))throw new TypeError("Expected `limit` to be a finite number");if(!_(s))throw new TypeError("Expected `interval` to be a finite number");var e=[],r=[],o=0,i=function(){o++;var c=setTimeout(function(){o--,e.length>0&&i(),r=r.filter(function(h){return h!==c})},s);r.indexOf(c)<0&&r.push(c);var l=e.shift();l.resolve(n.apply(l.self,l.args))},a=function(){var c=arguments,l=this;return new Promise(function(h,y){e.push({resolve:h,reject:y,args:c,self:l}),o<t&&i()})};return a.abort=function(){r.forEach(clearTimeout),r=[],e.forEach(function(c){c.reject(new throttle.AbortError)}),e.length=0},a}R.AbortError=function(){Error.call(this,"Throttled function aborted"),this.name="AbortError"};const O=function(n,t){if(!n)return null;let s={};for(let e in n){let r=n[e];t.indexOf(e)>-1&&r!==null&&(s[e]=r)}return s};var A={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:O(n.attrs,["src","alt","title"])}]}),list_item:()=>({tag:"li"}),ordered_list:()=>({tag:"ol"}),paragraph:()=>({tag:"p"})},marks:{bold:()=>({tag:"b"}),strike:()=>({tag:"strike"}),underline:()=>({tag:"u"}),strong:()=>({tag:"strong"}),code:()=>({tag:"code"}),italic:()=>({tag:"i"}),link(n){const t=g({},n.attrs),{linktype:s="url"}=n.attrs;return s==="email"&&(t.href=`mailto:${t.href}`),t.anchor&&(t.href=`${t.href}#${t.anchor}`,delete t.anchor),{tag:[{tag:"a",attrs:t}]}},styled:n=>({tag:[{tag:"span",attrs:n.attrs}]})}};class P{constructor(t){t||(t=A),this.marks=t.marks||[],this.nodes=t.nodes||[]}addNode(t,s){this.nodes[t]=s}addMark(t,s){this.marks[t]=s}render(t={}){if(t.content&&Array.isArray(t.content)){let s="";return t.content.forEach(e=>{s+=this.renderNode(e)}),s}return console.warn("The render method must receive an object with a content field, which is an array"),""}renderNode(t){let s=[];t.marks&&t.marks.forEach(r=>{const o=this.getMatchingMark(r);o&&s.push(this.renderOpeningTag(o.tag))});const e=this.getMatchingNode(t);return e&&e.tag&&s.push(this.renderOpeningTag(e.tag)),t.content?t.content.forEach(r=>{s.push(this.renderNode(r))}):t.text?s.push(function(r){const o={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},i=/[&<>"']/g,a=RegExp(i.source);return r&&a.test(r)?r.replace(i,c=>o[c]):r}(t.text)):e&&e.singleTag?s.push(this.renderTag(e.singleTag," /")):e&&e.html&&s.push(e.html),e&&e.tag&&s.push(this.renderClosingTag(e.tag)),t.marks&&t.marks.slice(0).reverse().forEach(r=>{const o=this.getMatchingMark(r);o&&s.push(this.renderClosingTag(o.tag))}),s.join("")}renderTag(t,s){return t.constructor===String?`<${t}${s}>`:t.map(e=>{if(e.constructor===String)return`<${e}${s}>`;{let r=`<${e.tag}`;if(e.attrs)for(let o in e.attrs){let i=e.attrs[o];i!==null&&(r+=` ${o}="${i}"`)}return`${r}${s}>`}}).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){if(typeof this.nodes[t.type]=="function")return this.nodes[t.type](t)}getMatchingMark(t){if(typeof this.marks[t.type]=="function")return this.marks[t.type](t)}}const C=(n=0,t=n)=>{const s=Math.abs(t-n)||0,e=n<t?1:-1;return((r=0,o)=>[...Array(r)].map(o))(s,(r,o)=>o*e+n)},b=(n,t,s)=>{const e=[];for(const r in n){if(!Object.prototype.hasOwnProperty.call(n,r))continue;const o=n[r],i=s?"":encodeURIComponent(r);let a;a=typeof o=="object"?b(o,t?t+encodeURIComponent("["+i+"]"):i,Array.isArray(o)):(t?t+encodeURIComponent("["+i+"]"):i)+"="+encodeURIComponent(o),e.push(a)}return e.join("&")};let m={},f={};class x{constructor(t,s){if(!s){let o=t.region?`-${t.region}`:"",i=t.https===!1?"http":"https";s=t.oauthToken===void 0?`${i}://api${o}.storyblok.com/v2`:`${i}://api${o}.storyblok.com/v1`}let e=Object.assign({},t.headers),r=5;t.oauthToken!==void 0&&(e.Authorization=t.oauthToken,r=3),t.rateLimit!==void 0&&(r=t.rateLimit),this.richTextResolver=new P(t.richTextSchema),typeof t.componentResolver=="function"&&this.setComponentResolver(t.componentResolver),this.maxRetries=t.maxRetries||5,this.throttle=R(this.throttledRequest,r,1e3),this.accessToken=t.accessToken,this.relations={},this.links={},this.cache=t.cache||{clear:"manual"},this.client=j.default.create({baseURL:s,timeout:t.timeout||0,headers:e,proxy:t.proxy||!1}),t.responseInterceptor&&this.client.interceptors.response.use(o=>t.responseInterceptor(o)),this.resolveNestedRelations=t.resolveNestedRelations||!0}setComponentResolver(t){this.richTextResolver.addNode("blok",s=>{let e="";return s.attrs.body.forEach(r=>{e+=t(r.component,r)}),{html:e}})}parseParams(t={}){return t.version||(t.version="published"),t.token||(t.token=this.getToken()),t.cv||(t.cv=f[t.token]),Array.isArray(t.resolve_relations)&&(t.resolve_relations=t.resolve_relations.join(",")),t}factoryParamOptions(t,s={}){return((e="")=>e.indexOf("/cdn/")>-1)(t)?this.parseParams(s):s}makeRequest(t,s,e,r){const o=this.factoryParamOptions(t,((i={},a=25,c=1)=>k(g({},i),{per_page:a,page:c}))(s,e,r));return this.cacheResponse(t,o)}get(t,s){let e=`/${t}`;const r=this.factoryParamOptions(e,s);return this.cacheResponse(e,r)}async getAll(t,s={},e){const r=s.per_page||25,o=`/${t}`,i=o.split("/");e=e||i[i.length-1];const a=await this.makeRequest(o,s,r,1),c=Math.ceil(a.total/r);return((l=[],h)=>l.map(h).reduce((y,L)=>[...y,...L],[]))([a,...await(async(l=[],h)=>Promise.all(l.map(h)))(C(1,c),async l=>this.makeRequest(o,s,r,l+1))],l=>Object.values(l.data[e]))}post(t,s){let e=`/${t}`;return this.throttle("post",e,s)}put(t,s){let e=`/${t}`;return this.throttle("put",e,s)}delete(t,s){let e=`/${t}`;return this.throttle("delete",e,s)}getStories(t){return this.get("cdn/stories",t)}getStory(t,s){return this.get(`cdn/stories/${t}`,s)}setToken(t){this.accessToken=t}getToken(){return this.accessToken}_cleanCopy(t){return JSON.parse(JSON.stringify(t))}_insertLinks(t,s){const e=t[s];e&&e.fieldtype=="multilink"&&e.linktype=="story"&&typeof e.id=="string"&&this.links[e.id]?e.story=this._cleanCopy(this.links[e.id]):e&&e.linktype==="story"&&typeof e.uuid=="string"&&this.links[e.uuid]&&(e.story=this._cleanCopy(this.links[e.uuid]))}_insertRelations(t,s,e){if(e.indexOf(t.component+"."+s)>-1){if(typeof t[s]=="string")this.relations[t[s]]&&(t[s]=this._cleanCopy(this.relations[t[s]]));else if(t[s].constructor===Array){let r=[];t[s].forEach(o=>{this.relations[o]&&r.push(this._cleanCopy(this.relations[o]))}),t[s]=r}}}_insertAssetsRelations(t,s){s.forEach(e=>{t.id===e.id&&(t.original=e,t.original.filename=t.filename,t.original.filename=t.original.filename.includes("https://s3.amazonaws.com/")?t.original.filename:t.original.filename.replace("https://","https://s3.amazonaws.com/"),delete t.original.s3_filename)})}iterateTree(t,s){let e=r=>{if(r!=null){if(r.constructor===Array)for(let o=0;o<r.length;o++)e(r[o]);else if(r.constructor===Object){if(r._stopResolving)return;for(let o in r)r.component&&r._uid||r.type==="link"?(this._insertRelations(r,o,s),this._insertLinks(r,o)):"id"in r&&r.fieldtype==="asset"&&this._insertAssetsRelations(r,s),e(r[o])}}};e(t.content)}async resolveLinks(t,s){let e=[];if(t.link_uuids){const r=t.link_uuids.length;let o=[];const i=50;for(let a=0;a<r;a+=i){const c=Math.min(r,a+i);o.push(t.link_uuids.slice(a,c))}for(let a=0;a<o.length;a++)(await this.getStories({per_page:i,language:s.language,version:s.version,by_uuids:o[a].join(",")})).data.stories.forEach(c=>{e.push(c)})}else e=t.links;e.forEach(r=>{this.links[r.uuid]=k(g({},r),{_stopResolving:!0})})}async resolveRelations(t,s){let e=[];if(t.rel_uuids){const r=t.rel_uuids.length;let o=[];const i=50;for(let a=0;a<r;a+=i){const c=Math.min(r,a+i);o.push(t.rel_uuids.slice(a,c))}for(let a=0;a<o.length;a++)(await this.getStories({per_page:i,language:s.language,version:s.version,by_uuids:o[a].join(",")})).data.stories.forEach(c=>{e.push(c)})}else e=t.rels;e.forEach(r=>{this.relations[r.uuid]=k(g({},r),{_stopResolving:!0})})}async resolveStories(t,s){let e=[];if(s.resolve_relations!==void 0&&s.resolve_relations.length>0&&(t.rels||t.rel_uuids)&&(e=s.resolve_relations.split(","),await this.resolveRelations(t,s)),["1","story","url"].indexOf(s.resolve_links)>-1&&(t.links||t.link_uuids)&&await this.resolveLinks(t,s),this.resolveNestedRelations)for(const r in this.relations)this.iterateTree(this.relations[r],e);t.story?this.iterateTree(t.story,e):t.stories.forEach(r=>{this.iterateTree(r,e)})}resolveAssetsRelations(t){const{assets:s,stories:e,story:r}=t;if(e)for(const o of e)this.iterateTree(o,s);else{if(!r)return t;this.iterateTree(r,s)}}cacheResponse(t,s,e){return e===void 0&&(e=0),new Promise(async(r,o)=>{let i=b({url:t,params:s}),a=this.cacheProvider();if(this.cache.clear==="auto"&&s.version==="draft"&&await this.flushCache(),s.version==="published"&&t!="/cdn/spaces/me"){const l=await a.get(i);if(l)return r(l)}try{let l=await this.throttle("get",t,{params:s,paramsSerializer:y=>b(y)}),h={data:l.data,headers:l.headers};if(h.data.assets&&h.data.assets.length&&this.resolveAssetsRelations(h.data),l.headers["per-page"]&&(h=Object.assign({},h,{perPage:parseInt(l.headers["per-page"]),total:parseInt(l.headers.total)})),l.status!=200)return o(l);(h.data.story||h.data.stories)&&await this.resolveStories(h.data,s),s.version==="published"&&t!="/cdn/spaces/me"&&a.set(i,h),h.data.cv&&(s.version=="draft"&&f[s.token]!=h.data.cv&&this.flushCache(),f[s.token]=h.data.cv),r(h)}catch(l){if(l.response&&l.response.status===429&&(e+=1)<this.maxRetries)return console.log(`Hit rate limit. Retrying in ${e} seconds.`),await(c=1e3*e,new Promise(h=>setTimeout(h,c))),this.cacheResponse(t,s,e).then(r).catch(o);o(l)}var c})}throttledRequest(t,s,e){return this.client[t](s,e)}cacheVersions(){return f}cacheVersion(){return f[this.accessToken]}setCacheVersion(t){this.accessToken&&(f[this.accessToken]=t)}cacheProvider(){return this.cache.type==="memory"?{get:t=>m[t],getAll:()=>m,set(t,s){m[t]=s},flush(){m={}}}:{get(){},getAll(){},set(){},flush(){}}}async flushCache(){return await this.cacheProvider().flush(),this}}const M=(n={})=>{const{apiOptions:t}=n;if(!t.accessToken){console.error("You need to provide an access token to interact with Storyblok API. Read https://www.storyblok.com/docs/api/content-delivery#topics/authentication");return}return{storyblokApi:new x(t)}};var N=n=>{if(typeof n!="object"||typeof n._editable=="undefined")return{};const t=JSON.parse(n._editable.replace(/^<!--#storyblok#/,"").replace(/-->$/,""));return{"data-blok-c":JSON.stringify(t),"data-blok-uid":t.id+"-"+t.uid}};const E="https://app.storyblok.com/f/storyblok-v2-latest.js",I=(n,t,s={})=>{if(typeof window!="undefined"){if(typeof window.storyblokRegisterEvent=="undefined"){console.error("Storyblok Bridge is disabled. Please enable it to use it. Read https://github.com/storyblok/storyblok-js");return}if(!n){console.warn("Story ID is not defined. Please provide a valid ID.");return}window.storyblokRegisterEvent(()=>{new window.StoryblokBridge(s).on(["input","published","change"],r=>{r.action=="input"&&r.story.id===n?t(r.story):window.location.reload()})})}},B=(n={})=>{const{bridge:t,accessToken:s,use:e=[],apiOptions:r={}}=n;r.accessToken=r.accessToken||s;const o={bridge:t,apiOptions:r};let i={};return e.forEach(a=>{i=g(g({},i),a(o))}),t!==!1&&T(E),i},q=()=>T(E);u.apiPlugin=M,u.loadStoryblokBridge=q,u.storyblokEditable=N,u.storyblokInit=B,u.useStoryblokBridge=I,Object.defineProperty(u,"__esModule",{value:!0}),u[Symbol.toStringTag]="Module"});
5
+ */function _(n){return typeof n=="number"&&n==n&&n!==1/0&&n!==-1/0}function R(n,t,e){if(!_(t))throw new TypeError("Expected `limit` to be a finite number");if(!_(e))throw new TypeError("Expected `interval` to be a finite number");var r=[],s=[],o=0,i=function(){o++;var c=setTimeout(function(){o--,r.length>0&&i(),s=s.filter(function(u){return u!==c})},e);s.indexOf(c)<0&&s.push(c);var l=r.shift();l.resolve(n.apply(l.self,l.args))},a=function(){var c=arguments,l=this;return new Promise(function(u,y){r.push({resolve:u,reject:y,args:c,self:l}),o<t&&i()})};return a.abort=function(){s.forEach(clearTimeout),s=[],r.forEach(function(c){c.reject(new throttle.AbortError)}),r.length=0},a}R.AbortError=function(){Error.call(this,"Throttled function aborted"),this.name="AbortError"};const N=function(n,t){if(!n)return null;let e={};for(let r in n){let s=n[r];t.indexOf(r)>-1&&s!==null&&(e[r]=s)}return e};var P={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:N(n.attrs,["src","alt","title"])}]}),list_item:()=>({tag:"li"}),ordered_list:()=>({tag:"ol"}),paragraph:()=>({tag:"p"})},marks:{bold:()=>({tag:"b"}),strike:()=>({tag:"strike"}),underline:()=>({tag:"u"}),strong:()=>({tag:"strong"}),code:()=>({tag:"code"}),italic:()=>({tag:"i"}),link(n){const t=p({},n.attrs),{linktype:e="url"}=n.attrs;return e==="email"&&(t.href=`mailto:${t.href}`),t.anchor&&(t.href=`${t.href}#${t.anchor}`,delete t.anchor),{tag:[{tag:"a",attrs:t}]}},styled:n=>({tag:[{tag:"span",attrs:n.attrs}]})}};class I{constructor(t){t||(t=P),this.marks=t.marks||[],this.nodes=t.nodes||[]}addNode(t,e){this.nodes[t]=e}addMark(t,e){this.marks[t]=e}render(t={}){if(t.content&&Array.isArray(t.content)){let e="";return t.content.forEach(r=>{e+=this.renderNode(r)}),e}return console.warn("The render method must receive an object with a content field, which is an array"),""}renderNode(t){let e=[];t.marks&&t.marks.forEach(s=>{const o=this.getMatchingMark(s);o&&e.push(this.renderOpeningTag(o.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(function(s){const o={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},i=/[&<>"']/g,a=RegExp(i.source);return s&&a.test(s)?s.replace(i,c=>o[c]):s}(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 o=this.getMatchingMark(s);o&&e.push(this.renderClosingTag(o.tag))}),e.join("")}renderTag(t,e){return t.constructor===String?`<${t}${e}>`:t.map(r=>{if(r.constructor===String)return`<${r}${e}>`;{let s=`<${r.tag}`;if(r.attrs)for(let o in r.attrs){let i=r.attrs[o];i!==null&&(s+=` ${o}="${i}"`)}return`${s}${e}>`}}).join("")}renderOpeningTag(t){return this.renderTag(t,"")}renderClosingTag(t){return t.constructor===String?`</${t}>`:t.slice(0).reverse().map(e=>e.constructor===String?`</${e}>`:`</${e.tag}>`).join("")}getMatchingNode(t){if(typeof this.nodes[t.type]=="function")return this.nodes[t.type](t)}getMatchingMark(t){if(typeof this.marks[t.type]=="function")return this.marks[t.type](t)}}const q=(n=0,t=n)=>{const e=Math.abs(t-n)||0,r=n<t?1:-1;return((s=0,o)=>[...Array(s)].map(o))(e,(s,o)=>o*r+n)},b=(n,t,e)=>{const r=[];for(const s in n){if(!Object.prototype.hasOwnProperty.call(n,s))continue;const o=n[s],i=e?"":encodeURIComponent(s);let a;a=typeof o=="object"?b(o,t?t+encodeURIComponent("["+i+"]"):i,Array.isArray(o)):(t?t+encodeURIComponent("["+i+"]"):i)+"="+encodeURIComponent(o),r.push(a)}return r.join("&")};let k={},f={};class B{constructor(t,e){if(!e){let o=t.region?`-${t.region}`:"",i=t.https===!1?"http":"https";e=t.oauthToken===void 0?`${i}://api${o}.storyblok.com/v2`:`${i}://api${o}.storyblok.com/v1`}let r=Object.assign({},t.headers),s=5;t.oauthToken!==void 0&&(r.Authorization=t.oauthToken,s=3),t.rateLimit!==void 0&&(s=t.rateLimit),this.richTextResolver=new I(t.richTextSchema),typeof t.componentResolver=="function"&&this.setComponentResolver(t.componentResolver),this.maxRetries=t.maxRetries||5,this.throttle=R(this.throttledRequest,s,1e3),this.accessToken=t.accessToken,this.relations={},this.links={},this.cache=t.cache||{clear:"manual"},this.client=S.default.create({baseURL:e,timeout:t.timeout||0,headers:r,proxy:t.proxy||!1}),t.responseInterceptor&&this.client.interceptors.response.use(o=>t.responseInterceptor(o)),this.resolveNestedRelations=t.resolveNestedRelations||!0}setComponentResolver(t){this.richTextResolver.addNode("blok",e=>{let r="";return e.attrs.body.forEach(s=>{r+=t(s.component,s)}),{html:r}})}parseParams(t={}){return t.version||(t.version="published"),t.token||(t.token=this.getToken()),t.cv||(t.cv=f[t.token]),Array.isArray(t.resolve_relations)&&(t.resolve_relations=t.resolve_relations.join(",")),t}factoryParamOptions(t,e={}){return((r="")=>r.indexOf("/cdn/")>-1)(t)?this.parseParams(e):e}makeRequest(t,e,r,s){const o=this.factoryParamOptions(t,((i={},a=25,c=1)=>m(p({},i),{per_page:a,page:c}))(e,r,s));return this.cacheResponse(t,o)}get(t,e){let r=`/${t}`;const s=this.factoryParamOptions(r,e);return this.cacheResponse(r,s)}async getAll(t,e={},r){const s=e.per_page||25,o=`/${t}`,i=o.split("/");r=r||i[i.length-1];const a=await this.makeRequest(o,e,s,1),c=Math.ceil(a.total/s);return((l=[],u)=>l.map(u).reduce((y,F)=>[...y,...F],[]))([a,...await(async(l=[],u)=>Promise.all(l.map(u)))(q(1,c),async l=>this.makeRequest(o,e,s,l+1))],l=>Object.values(l.data[r]))}post(t,e){let r=`/${t}`;return this.throttle("post",r,e)}put(t,e){let r=`/${t}`;return this.throttle("put",r,e)}delete(t,e){let r=`/${t}`;return this.throttle("delete",r,e)}getStories(t){return this.get("cdn/stories",t)}getStory(t,e){return this.get(`cdn/stories/${t}`,e)}setToken(t){this.accessToken=t}getToken(){return this.accessToken}_cleanCopy(t){return JSON.parse(JSON.stringify(t))}_insertLinks(t,e){const r=t[e];r&&r.fieldtype=="multilink"&&r.linktype=="story"&&typeof r.id=="string"&&this.links[r.id]?r.story=this._cleanCopy(this.links[r.id]):r&&r.linktype==="story"&&typeof r.uuid=="string"&&this.links[r.uuid]&&(r.story=this._cleanCopy(this.links[r.uuid]))}_insertRelations(t,e,r){if(r.indexOf(t.component+"."+e)>-1){if(typeof t[e]=="string")this.relations[t[e]]&&(t[e]=this._cleanCopy(this.relations[t[e]]));else if(t[e].constructor===Array){let s=[];t[e].forEach(o=>{this.relations[o]&&s.push(this._cleanCopy(this.relations[o]))}),t[e]=s}}}_insertAssetsRelations(t,e){e.forEach(r=>{t.id===r.id&&(t.original=r,t.original.filename=t.filename,t.original.filename=t.original.filename.includes("https://s3.amazonaws.com/")?t.original.filename:t.original.filename.replace("https://","https://s3.amazonaws.com/"),delete t.original.s3_filename)})}iterateTree(t,e){let r=s=>{if(s!=null){if(s.constructor===Array)for(let o=0;o<s.length;o++)r(s[o]);else if(s.constructor===Object){if(s._stopResolving)return;for(let o in s)s.component&&s._uid||s.type==="link"?(this._insertRelations(s,o,e),this._insertLinks(s,o)):"id"in s&&s.fieldtype==="asset"&&this._insertAssetsRelations(s,e),r(s[o])}}};r(t.content)}async resolveLinks(t,e){let r=[];if(t.link_uuids){const s=t.link_uuids.length;let o=[];const i=50;for(let a=0;a<s;a+=i){const c=Math.min(s,a+i);o.push(t.link_uuids.slice(a,c))}for(let a=0;a<o.length;a++)(await this.getStories({per_page:i,language:e.language,version:e.version,by_uuids:o[a].join(",")})).data.stories.forEach(c=>{r.push(c)})}else r=t.links;r.forEach(s=>{this.links[s.uuid]=m(p({},s),{_stopResolving:!0})})}async resolveRelations(t,e){let r=[];if(t.rel_uuids){const s=t.rel_uuids.length;let o=[];const i=50;for(let a=0;a<s;a+=i){const c=Math.min(s,a+i);o.push(t.rel_uuids.slice(a,c))}for(let a=0;a<o.length;a++)(await this.getStories({per_page:i,language:e.language,version:e.version,by_uuids:o[a].join(",")})).data.stories.forEach(c=>{r.push(c)})}else r=t.rels;r.forEach(s=>{this.relations[s.uuid]=m(p({},s),{_stopResolving:!0})})}async resolveStories(t,e){let r=[];if(e.resolve_relations!==void 0&&e.resolve_relations.length>0&&(t.rels||t.rel_uuids)&&(r=e.resolve_relations.split(","),await this.resolveRelations(t,e)),["1","story","url"].indexOf(e.resolve_links)>-1&&(t.links||t.link_uuids)&&await this.resolveLinks(t,e),this.resolveNestedRelations)for(const s in this.relations)this.iterateTree(this.relations[s],r);t.story?this.iterateTree(t.story,r):t.stories.forEach(s=>{this.iterateTree(s,r)})}resolveAssetsRelations(t){const{assets:e,stories:r,story:s}=t;if(r)for(const o of r)this.iterateTree(o,e);else{if(!s)return t;this.iterateTree(s,e)}}cacheResponse(t,e,r){return r===void 0&&(r=0),new Promise(async(s,o)=>{let i=b({url:t,params:e}),a=this.cacheProvider();if(this.cache.clear==="auto"&&e.version==="draft"&&await this.flushCache(),e.version==="published"&&t!="/cdn/spaces/me"){const l=await a.get(i);if(l)return s(l)}try{let l=await this.throttle("get",t,{params:e,paramsSerializer:y=>b(y)}),u={data:l.data,headers:l.headers};if(u.data.assets&&u.data.assets.length&&this.resolveAssetsRelations(u.data),l.headers["per-page"]&&(u=Object.assign({},u,{perPage:parseInt(l.headers["per-page"]),total:parseInt(l.headers.total)})),l.status!=200)return o(l);(u.data.story||u.data.stories)&&await this.resolveStories(u.data,e),e.version==="published"&&t!="/cdn/spaces/me"&&a.set(i,u),u.data.cv&&(e.version=="draft"&&f[e.token]!=u.data.cv&&this.flushCache(),f[e.token]=u.data.cv),s(u)}catch(l){if(l.response&&l.response.status===429&&(r+=1)<this.maxRetries)return console.log(`Hit rate limit. Retrying in ${r} seconds.`),await(c=1e3*r,new Promise(u=>setTimeout(u,c))),this.cacheResponse(t,e,r).then(s).catch(o);o(l)}var c})}throttledRequest(t,e,r){return this.client[t](e,r)}cacheVersions(){return f}cacheVersion(){return f[this.accessToken]}setCacheVersion(t){this.accessToken&&(f[this.accessToken]=t)}cacheProvider(){return this.cache.type==="memory"?{get:t=>k[t],getAll:()=>k,set(t,e){k[t]=e},flush(){k={}}}:{get(){},getAll(){},set(){},flush(){}}}async flushCache(){return await this.cacheProvider().flush(),this}}const L=(n={})=>{const{apiOptions:t}=n;if(!t.accessToken){console.error("You need to provide an access token to interact with Storyblok API. Read https://www.storyblok.com/docs/api/content-delivery#topics/authentication");return}return{storyblokApi:new B(t)}};var z=n=>{if(typeof n!="object"||typeof n._editable=="undefined")return{};const t=JSON.parse(n._editable.replace(/^<!--#storyblok#/,"").replace(/-->$/,""));return{"data-blok-c":JSON.stringify(t),"data-blok-uid":t.id+"-"+t.uid}};const U=new C,$="https://app.storyblok.com/f/storyblok-v2-latest.js",H=(n,t,e={})=>{if(typeof window!="undefined"){if(typeof window.storyblokRegisterEvent=="undefined"){console.error("Storyblok Bridge is disabled. Please enable it to use it. Read https://github.com/storyblok/storyblok-js");return}if(!n){console.warn("Story ID is not defined. Please provide a valid ID.");return}window.storyblokRegisterEvent(()=>{new window.StoryblokBridge(e).on(["input","published","change"],s=>{s.action=="input"&&s.story.id===n?t(s.story):window.location.reload()})})}},D=(n={})=>{const{bridge:t,accessToken:e,use:r=[],apiOptions:s={}}=n;s.accessToken=s.accessToken||e;const o={bridge:t,apiOptions:s};let i={};return r.forEach(a=>{i=p(p({},i),a(o))}),t!==!1&&w($),i},J=n=>n===""?"":n?U.render(n):(console.warn(`${n} is not a valid Richtext object. This might be because the value of the richtext field is empty.
6
+
7
+ For more info about the richtext object check https://github.com/storyblok/storyblok-js#rendering-rich-text`),""),V=()=>w($);h.apiPlugin=L,h.loadStoryblokBridge=V,h.renderRichText=J,h.storyblokEditable=z,h.storyblokInit=D,h.useStoryblokBridge=H,Object.defineProperty(h,"__esModule",{value:!0}),h[Symbol.toStringTag]="Module"});
@@ -49,6 +49,272 @@ const loadBridge = (src) => {
49
49
  document.getElementsByTagName("head")[0].appendChild(script);
50
50
  });
51
51
  };
52
+ const pick = function(attrs, allowed) {
53
+ if (!attrs) {
54
+ return null;
55
+ }
56
+ let h2 = {};
57
+ for (let key in attrs) {
58
+ let value = attrs[key];
59
+ if (allowed.indexOf(key) > -1 && value !== null) {
60
+ h2[key] = value;
61
+ }
62
+ }
63
+ return h2;
64
+ };
65
+ const isEmailLinkType = (type) => type === "email";
66
+ var defaultHtmlSerializer = {
67
+ nodes: {
68
+ horizontal_rule() {
69
+ return {
70
+ singleTag: "hr"
71
+ };
72
+ },
73
+ blockquote() {
74
+ return {
75
+ tag: "blockquote"
76
+ };
77
+ },
78
+ bullet_list() {
79
+ return {
80
+ tag: "ul"
81
+ };
82
+ },
83
+ code_block(node) {
84
+ return {
85
+ tag: [
86
+ "pre",
87
+ {
88
+ tag: "code",
89
+ attrs: node.attrs
90
+ }
91
+ ]
92
+ };
93
+ },
94
+ hard_break() {
95
+ return {
96
+ singleTag: "br"
97
+ };
98
+ },
99
+ heading(node) {
100
+ return {
101
+ tag: `h${node.attrs.level}`
102
+ };
103
+ },
104
+ image(node) {
105
+ return {
106
+ singleTag: [
107
+ {
108
+ tag: "img",
109
+ attrs: pick(node.attrs, ["src", "alt", "title"])
110
+ }
111
+ ]
112
+ };
113
+ },
114
+ list_item() {
115
+ return {
116
+ tag: "li"
117
+ };
118
+ },
119
+ ordered_list() {
120
+ return {
121
+ tag: "ol"
122
+ };
123
+ },
124
+ paragraph() {
125
+ return {
126
+ tag: "p"
127
+ };
128
+ }
129
+ },
130
+ marks: {
131
+ bold() {
132
+ return {
133
+ tag: "b"
134
+ };
135
+ },
136
+ strike() {
137
+ return {
138
+ tag: "strike"
139
+ };
140
+ },
141
+ underline() {
142
+ return {
143
+ tag: "u"
144
+ };
145
+ },
146
+ strong() {
147
+ return {
148
+ tag: "strong"
149
+ };
150
+ },
151
+ code() {
152
+ return {
153
+ tag: "code"
154
+ };
155
+ },
156
+ italic() {
157
+ return {
158
+ tag: "i"
159
+ };
160
+ },
161
+ link(node) {
162
+ const attrs = __spreadValues({}, node.attrs);
163
+ const { linktype = "url" } = node.attrs;
164
+ if (isEmailLinkType(linktype)) {
165
+ attrs.href = `mailto:${attrs.href}`;
166
+ }
167
+ if (attrs.anchor) {
168
+ attrs.href = `${attrs.href}#${attrs.anchor}`;
169
+ delete attrs.anchor;
170
+ }
171
+ return {
172
+ tag: [
173
+ {
174
+ tag: "a",
175
+ attrs
176
+ }
177
+ ]
178
+ };
179
+ },
180
+ styled(node) {
181
+ return {
182
+ tag: [
183
+ {
184
+ tag: "span",
185
+ attrs: node.attrs
186
+ }
187
+ ]
188
+ };
189
+ }
190
+ }
191
+ };
192
+ const escapeHTML = function(string) {
193
+ const htmlEscapes = {
194
+ "&": "&amp;",
195
+ "<": "&lt;",
196
+ ">": "&gt;",
197
+ '"': "&quot;",
198
+ "'": "&#39;"
199
+ };
200
+ const reUnescapedHtml = /[&<>"']/g;
201
+ const reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
202
+ return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, (chr) => htmlEscapes[chr]) : string;
203
+ };
204
+ class RichTextResolver {
205
+ constructor(schema) {
206
+ if (!schema) {
207
+ schema = defaultHtmlSerializer;
208
+ }
209
+ this.marks = schema.marks || [];
210
+ this.nodes = schema.nodes || [];
211
+ }
212
+ addNode(key, schema) {
213
+ this.nodes[key] = schema;
214
+ }
215
+ addMark(key, schema) {
216
+ this.marks[key] = schema;
217
+ }
218
+ render(data = {}) {
219
+ if (data.content && Array.isArray(data.content)) {
220
+ let html = "";
221
+ data.content.forEach((node) => {
222
+ html += this.renderNode(node);
223
+ });
224
+ return html;
225
+ }
226
+ console.warn("The render method must receive an object with a content field, which is an array");
227
+ return "";
228
+ }
229
+ renderNode(item) {
230
+ let html = [];
231
+ if (item.marks) {
232
+ item.marks.forEach((m) => {
233
+ const mark = this.getMatchingMark(m);
234
+ if (mark) {
235
+ html.push(this.renderOpeningTag(mark.tag));
236
+ }
237
+ });
238
+ }
239
+ const node = this.getMatchingNode(item);
240
+ if (node && node.tag) {
241
+ html.push(this.renderOpeningTag(node.tag));
242
+ }
243
+ if (item.content) {
244
+ item.content.forEach((content) => {
245
+ html.push(this.renderNode(content));
246
+ });
247
+ } else if (item.text) {
248
+ html.push(escapeHTML(item.text));
249
+ } else if (node && node.singleTag) {
250
+ html.push(this.renderTag(node.singleTag, " /"));
251
+ } else if (node && node.html) {
252
+ html.push(node.html);
253
+ }
254
+ if (node && node.tag) {
255
+ html.push(this.renderClosingTag(node.tag));
256
+ }
257
+ if (item.marks) {
258
+ item.marks.slice(0).reverse().forEach((m) => {
259
+ const mark = this.getMatchingMark(m);
260
+ if (mark) {
261
+ html.push(this.renderClosingTag(mark.tag));
262
+ }
263
+ });
264
+ }
265
+ return html.join("");
266
+ }
267
+ renderTag(tags, ending) {
268
+ if (tags.constructor === String) {
269
+ return `<${tags}${ending}>`;
270
+ }
271
+ const all = tags.map((tag) => {
272
+ if (tag.constructor === String) {
273
+ return `<${tag}${ending}>`;
274
+ } else {
275
+ let h2 = `<${tag.tag}`;
276
+ if (tag.attrs) {
277
+ for (let key in tag.attrs) {
278
+ let value = tag.attrs[key];
279
+ if (value !== null) {
280
+ h2 += ` ${key}="${value}"`;
281
+ }
282
+ }
283
+ }
284
+ return `${h2}${ending}>`;
285
+ }
286
+ });
287
+ return all.join("");
288
+ }
289
+ renderOpeningTag(tags) {
290
+ return this.renderTag(tags, "");
291
+ }
292
+ renderClosingTag(tags) {
293
+ if (tags.constructor === String) {
294
+ return `</${tags}>`;
295
+ }
296
+ const all = tags.slice(0).reverse().map((tag) => {
297
+ if (tag.constructor === String) {
298
+ return `</${tag}>`;
299
+ } else {
300
+ return `</${tag.tag}>`;
301
+ }
302
+ });
303
+ return all.join("");
304
+ }
305
+ getMatchingNode(item) {
306
+ if (typeof this.nodes[item.type] !== "function") {
307
+ return;
308
+ }
309
+ return this.nodes[item.type](item);
310
+ }
311
+ getMatchingMark(item) {
312
+ if (typeof this.marks[item.type] !== "function") {
313
+ return;
314
+ }
315
+ return this.marks[item.type](item);
316
+ }
317
+ }
52
318
  /*!
53
319
  * storyblok-js-client v4.5.2
54
320
  * Universal JavaScript SDK for Storyblok's API
@@ -417,6 +683,7 @@ var editable = (blok) => {
417
683
  "data-blok-uid": options.id + "-" + options.uid
418
684
  };
419
685
  };
686
+ const resolver = new RichTextResolver();
420
687
  const bridgeLatest = "https://app.storyblok.com/f/storyblok-v2-latest.js";
421
688
  const useStoryblokBridge = (id, cb, options = {}) => {
422
689
  if (typeof window === "undefined") {
@@ -454,7 +721,16 @@ const storyblokInit = (pluginOptions = {}) => {
454
721
  }
455
722
  return result;
456
723
  };
457
- const loadStoryblokBridge = () => {
458
- return loadBridge(bridgeLatest);
724
+ const renderRichText = (text) => {
725
+ if (text === "") {
726
+ return "";
727
+ } else if (!text) {
728
+ console.warn(`${text} is not a valid Richtext object. This might be because the value of the richtext field is empty.
729
+
730
+ For more info about the richtext object check https://github.com/storyblok/storyblok-js#rendering-rich-text`);
731
+ return "";
732
+ }
733
+ return resolver.render(text);
459
734
  };
460
- export { apiFactory as apiPlugin, loadStoryblokBridge, editable as storyblokEditable, storyblokInit, useStoryblokBridge };
735
+ const loadStoryblokBridge = () => loadBridge(bridgeLatest);
736
+ export { apiFactory as apiPlugin, loadStoryblokBridge, renderRichText, editable as storyblokEditable, storyblokInit, useStoryblokBridge };
@@ -1,7 +1,8 @@
1
- import { SbSDKOptions, StoryblokBridgeConfigV2, StoryData, SbInitResult } from "./types";
2
- export declare const useStoryblokBridge: <T = void>(id: Number, cb: (newStory: StoryData<T>) => void, options?: StoryblokBridgeConfigV2) => void;
1
+ import { SbSDKOptions, StoryblokBridgeConfigV2, StoryData, SbInitResult, Richtext, StoryblokComponentType } from "./types";
2
+ export declare const useStoryblokBridge: <T extends StoryblokComponentType<string> = any>(id: Number, cb: (newStory: StoryData<T>) => void, options?: StoryblokBridgeConfigV2) => void;
3
3
  export { default as apiPlugin } from "./modules/api";
4
4
  export { default as storyblokEditable } from "./modules/editable";
5
5
  export declare const storyblokInit: (pluginOptions?: SbSDKOptions) => SbInitResult;
6
+ export declare const renderRichText: (text: Richtext) => string;
6
7
  export declare const loadStoryblokBridge: () => Promise<unknown>;
7
8
  export * from "./types";
@@ -26,6 +26,7 @@ export interface StoryblokBridgeConfigV2 {
26
26
  resolveRelations?: string[];
27
27
  customParent?: string;
28
28
  preventClicks?: boolean;
29
+ language?: string;
29
30
  }
30
31
  export interface StoryblokBridgeV2 {
31
32
  pingEditor: (event: any) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storyblok/js",
3
- "version": "1.6.5",
3
+ "version": "1.7.1",
4
4
  "description": "SDK to integrate Storyblok into your project using JavaScript.",
5
5
  "main": "./dist/storyblok-js.js",
6
6
  "module": "./dist/storyblok-js.mjs",