@storyblok/nuxt 2.0.5 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,7 +27,7 @@
27
27
  </a>
28
28
  </p>
29
29
 
30
- **Note**: This plugin is for Nuxt 2. [Check out the @next version for Nuxt 3](https://github.com/storyblok/storyblok-nuxt/tree/next)
30
+ **Note**: This module is for Nuxt 2. [Check out `@storyblok/nuxt-beta` for Nuxt 3](https://github.com/storyblok/storyblok-nuxt-beta)
31
31
 
32
32
  ## 🚀 Usage
33
33
 
@@ -35,166 +35,155 @@
35
35
 
36
36
  ### Installation
37
37
 
38
- Install `@storyblok/nuxt` and `axios` as its peer dependency:
38
+ Install `@storyblok/nuxt`:
39
39
 
40
40
  ```bash
41
- npm install --save-dev @storyblok/nuxt axios
42
- # yarn add -D @storyblok/nuxt axios
41
+ npm install @storyblok/nuxt
42
+ # yarn add @storyblok/nuxt
43
43
  ```
44
44
 
45
- > _Hint: You don't have to install Axios if you already installed Axios module of Nuxt._
46
-
47
- Add following code to modules section of `nuxt.config.js` and replace the accessToken with API token from Storyblok space.
45
+ Initialize the module by adding it to buildModules section of `nuxt.config.js` and replace the accessToken with API token from Storyblok space.
48
46
 
49
47
  ```js
50
48
  {
51
- modules: [
52
- [
53
- "@storyblok/nuxt",
54
- {
55
- accessToken: "YOUR_PREVIEW_TOKEN",
56
- cacheProvider: "memory",
57
- },
58
- ],
49
+ buildModules: [
50
+ // ...
51
+ ["@storyblok/nuxt/module", { accessToken: "<your-access-token>" }],
59
52
  ];
60
53
  }
61
54
  ```
62
55
 
63
- ### Getting started
56
+ #### Options
64
57
 
65
- This module adds two objects to the the Nuxt.js context.
58
+ When you initialize the module, you can pass all [_@storyblok/vue_ options](https://github.com/storyblok/storyblok-vue#storyblok-api) plus a `useApiClient` options:
66
59
 
67
- 1. $storyapi: The [Storyblok API client](https://github.com/storyblok/storyblok-nuxt).
68
- 2. $storybridge: A loader for the [Storyblok JS bridge](https://www.storyblok.com/docs/Guides/storyblok-latest-js?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-nuxt) that is responsible for adding the editing interface to your website.
60
+ ```js
61
+ // Defaults
62
+ ["@storyblok/nuxt/module", {
63
+ {
64
+ accessToken: "<your-access-token>",
65
+ bridge: process.env.NODE_ENV !== "production", // bridge is disabled in production by default
66
+ apiOptions: {}, // storyblok-js-client options
67
+ useApiClient: true
68
+ }
69
+ }]
70
+ ```
69
71
 
70
- Example of fetching data of the homepage and listening to the change events of the JS bridge:
72
+ ## Getting started
71
73
 
72
- ```js
73
- export default {
74
- data() {
75
- return {
76
- story: { content: {} },
77
- };
78
- },
79
- mounted() {
80
- this.$storybridge(
81
- () => {
82
- const storyblokInstance = new StoryblokBridge();
83
-
84
- storyblokInstance.on(["input", "published", "change"], (event) => {
85
- if (event.action == "input") {
86
- if (event.story.id === this.story.id) {
87
- this.story.content = event.story.content;
88
- }
89
- } else {
90
- window.location.reload();
91
- }
92
- });
93
- },
94
- (error) => {
95
- console.error(error);
96
- }
97
- );
98
- },
99
- asyncData(context) {
100
- return context.app.$storyapi
101
- .get("cdn/stories/home", {
102
- version: "draft",
103
- })
104
- .then((res) => {
105
- return res.data;
106
- })
107
- .catch((res) => {
108
- if (!res.response) {
109
- console.error(res);
110
- context.error({
111
- statusCode: 404,
112
- message: "Failed to receive content form api",
113
- });
114
- } else {
115
- console.error(res.response.data);
116
- context.error({
117
- statusCode: res.response.status,
118
- message: res.response.data,
119
- });
120
- }
121
- });
122
- },
123
- };
74
+ ### 1. Creating and linking your components to Storyblok Visual Editor
75
+
76
+ To link your Vue components to their equivalent you created in Storyblok:
77
+
78
+ - First, you need to load them globally. If you use Nuxt 2.13+, you can just place them on the `~/components/storyblok` directory, otherwise you can load them globally (for example, by [using a Nuxt plugin](https://stackoverflow.com/questions/43040692/global-components-in-vue-nuxt)).
79
+
80
+ - For each components, use the `v-editable` directive on its root element, passing the `blok` property that they receive:
81
+
82
+ ```html
83
+ <div v-editable="blok" / >
124
84
  ```
125
85
 
126
- > _Hint: Find out more how to use Nuxt together with Storyblok in [Nuxt Technology Hub](https://www.storyblok.com/tc/nuxtjs?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-nuxt)_
86
+ - Finally, use `<StoryblokComponent>` which available globally in the Nuxt app:
127
87
 
128
- ### API
88
+ ```html
89
+ <StoryblokComponent blok="blok" />
90
+ ```
129
91
 
130
- Like described above, this package includes two objects into Nuxt.js context:
92
+ > The `blok` is the actual blok data coming from [Storblok's Content Delivery API](https://www.storyblok.com/docs/api/content-delivery/v2?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-nuxt).
131
93
 
132
- #### $storyapi
94
+ ### 2. Getting Storyblok Stories and listen to Visual Editor events
133
95
 
134
- This object is a instance of StoryblokClient. You can check the documentation about StoryblokClient in the repository: https://github.com/storyblok/storyblok-nuxt
96
+ #### Composition API
135
97
 
136
- #### $storybridge(successCallback, errorCallback)
98
+ > To use Nuxt 2 with Composition API, make sure you installed the [@nuxtjs/composition-api](https://composition-api.nuxtjs.org/) plugin.
137
99
 
138
- You can use this object to load the [Storyblok JS Bridge](https://www.storyblok.com/docs/Guides/storyblok-latest-js?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-nuxt). In the success callback you will it have available in the window variable StoryblokBridge.
100
+ The simplest way is by using the `useStoryblok` one-liner composable:
139
101
 
140
- ### Migrate from 1.x to 2.x
102
+ ```html
103
+ <script setup>
104
+ import { useStoryblok } from "@storyblok/nuxt";
105
+ const story = useStoryblok("vue/test", { version: "draft" });
106
+ </script>
141
107
 
142
- #### Listening to Visual Editor events in 1.x
108
+ <template>
109
+ <StoryblokComponent v-if="story" :blok="story.content" />
110
+ </template>
111
+ ```
143
112
 
144
- Most of our tutorials and recordings still using following deprecated approach for real-time editing and listening to Storyblok's Visual Editor events. **This approach can be used only with 1.x version of the storyblok-nuxt.**
113
+ Which is the short-hand equivalent to using `useStoryblokApi` and `useStoryblokBridge` functions separately:
145
114
 
146
- ```js
147
- export default {
148
- mounted() {
149
- // Use the input event for instant update of content
150
- this.$storybridge.on("input", (event) => {
151
- if (event.story.id === this.story.id) {
152
- this.story.content = event.story.content;
153
- }
154
- });
155
- // Use the bridge to listen the events
156
- this.$storybridge.on(["published", "change"], (event) => {
157
- this.$nuxt.$router.go({
158
- path: this.$nuxt.$router.currentRoute,
159
- force: true,
160
- });
115
+ ```html
116
+ <script setup>
117
+ import { onMounted, ref } from "@nuxtjs/composition-api";
118
+ import { useStoryblokBridge, useStoryblokApi } from "@storyblok/nuxt";
119
+
120
+ const story = ref(null);
121
+
122
+ onMounted(async () => {
123
+ const storyblokApi = useStoryblokApi();
124
+ const { data } = await storyblokApi.get("cdn/stories/vue/test", {
125
+ version: "draft",
161
126
  });
162
- },
163
- };
127
+ story.value = data.story;
128
+
129
+ useStoryblokBridge(story.value.id, (evStory) => (story.value = evStory));
130
+ });
131
+ </script>
132
+
133
+ <template>
134
+ <StoryblokComponent v-if="story" :blok="story.content" />
135
+ </template>
164
136
  ```
165
137
 
166
- #### Listening to Visual Editor events in 2.x
138
+ #### Options API
167
139
 
168
- The recommended approach for 2.x storyblok-nuxt plugin.
140
+ You can still use the `useStoryblokApi` and `useStoryblokBridge` as follows:
169
141
 
170
- ```js
171
- export default {
172
- mounted() {
173
- this.$storybridge(
174
- () => {
175
- const storyblokInstance = new StoryblokBridge();
176
-
177
- storyblokInstance.on(["input", "published", "change"], (event) => {
178
- if (event.action == "input") {
179
- if (event.story.id === this.story.id) {
180
- this.story.content = event.story.content;
181
- }
182
- } else {
183
- this.$nuxt.$router.go({
184
- path: this.$nuxt.$router.currentRoute,
185
- force: true,
186
- });
187
- }
188
- });
189
- },
190
- (error) => {
191
- console.error(error);
192
- }
193
- );
194
- },
195
- };
142
+ ```html
143
+ <script>
144
+ import { useStoryblokBridge, useStoryblokApi } from "@storyblok/nuxt";
145
+
146
+ export default {
147
+ asyncData: async ({ app }) => {
148
+ const storyblokApi = useStoryblokApi();
149
+ const { data } = await storyblokApi.get("cdn/stories/vue", {
150
+ version: "draft",
151
+ });
152
+ // OR: const { data } = await app.$storyapi.get("cdn/stories/vue", { version: "draft" });
153
+
154
+ return { story: data.story };
155
+ },
156
+ mounted() {
157
+ useStoryblokBridge(this.story.id, (newStory) => (this.story = newStory));
158
+ },
159
+ };
160
+ </script>
161
+
162
+ <template>
163
+ <StoryblokComponent v-if="story" :blok="story.content" />
164
+ </template>
196
165
  ```
197
166
 
167
+ > _As you see in the comment, you can also use `app.$storyapi` if that's more comfortable for you. It's injected into Nuxt context and available in the components instance via `this.$storyapi` as well._
168
+
169
+ ### API
170
+
171
+ #### useStoryblok(slug, apiOptions, bridgeOptions)
172
+
173
+ Check the available [apiOptions](https://github.com/storyblok/storyblok-js-client#class-storyblok) (passed to `storyblok-js-client`) and [bridgeOptions](https://www.storyblok.com/docs/Guides/storyblok-latest-js?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-nuxt) (passed to the Storyblok Bridge).
174
+
175
+ #### useStoryblokApi()
176
+
177
+ Returns the instance of the `storyblok-js-client`.
178
+
179
+ #### useStoryblokBridge(storyId, callback, bridgeOptions)
180
+
181
+ Use this one-line function to cover the most common use case: updating the story when any kind of change happens on Storyblok Visual Editor.
182
+
183
+ #### $storyapi
184
+
185
+ Equivalent to the client that `useStoryblokApi` returns, but accessible in the Nuxt context and components instance.
186
+
198
187
  ## 🔗 Related Links
199
188
 
200
189
  - **[Nuxt.js Hub](https://www.storyblok.com/tc/nuxtjs?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-nuxt)**: Learn how to develop your own Nuxt.js applications that use Storyblok APIs to retrieve and manage content;
@@ -212,7 +201,3 @@ export default {
212
201
 
213
202
  Please see our [contributing guidelines](https://github.com/storyblok/.github/blob/master/contributing.md) and our [code of conduct](https://www.storyblok.com/trust-center#code-of-conduct?utm_source=github.com&utm_medium=readme&utm_campaign=storyblok-nuxt).
214
203
  This project use [semantic-release](https://semantic-release.gitbook.io/semantic-release/) for generate new versions by using commit messages and we use the Angular Convention to naming the commits. Check [this question](https://semantic-release.gitbook.io/semantic-release/support/faq#how-can-i-change-the-type-of-commits-that-trigger-a-release) about it in semantic-release FAQ.
215
-
216
- ### License
217
-
218
- This repository is published under the [MIT](./LICENSE) license.
@@ -0,0 +1,6 @@
1
+ (function(h,y){typeof exports=="object"&&typeof module!="undefined"?y(exports,require("axios"),require("@vue/composition-api")):typeof define=="function"&&define.amd?define(["exports","axios","@vue/composition-api"],y):(h=typeof globalThis!="undefined"?globalThis:h||self,y(h.storyblokNuxt={},h.t,h.VueCompositionAPI))})(this,function(h,y,_){"use strict";function N(s){return s&&typeof s=="object"&&"default"in s?s:{default:s}}var V=N(y),q=Object.defineProperty,x=Object.defineProperties,B=Object.getOwnPropertyDescriptors,w=Object.getOwnPropertySymbols,L=Object.prototype.hasOwnProperty,U=Object.prototype.propertyIsEnumerable,T=(s,e,t)=>e in s?q(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t,f=(s,e)=>{for(var t in e||(e={}))L.call(e,t)&&T(s,t,e[t]);if(w)for(var t of w(e))U.call(e,t)&&T(s,t,e[t]);return s},k=(s,e)=>x(s,B(e));let R=!1;const S=[],z=s=>new Promise((e,t)=>{if(typeof window=="undefined"||(window.storyblokRegisterEvent=o=>{if(window.location===window.parent.location){console.warn("You are not in Draft Mode or in the Visual Editor.");return}R?o():S.push(o)},document.getElementById("storyblok-javascript-bridge")))return;const r=document.createElement("script");r.async=!0,r.src=s,r.id="storyblok-javascript-bridge",r.onerror=o=>t(o),r.onload=o=>{S.forEach(n=>n()),R=!0,e(o)},document.getElementsByTagName("head")[0].appendChild(r)});/*!
2
+ * storyblok-js-client v0.0.0-development
3
+ * Universal JavaScript SDK for Storyblok's API
4
+ * (c) 2020-2022 Stobylok Team
5
+ */function O(s){return typeof s=="number"&&s==s&&s!==1/0&&s!==-1/0}function E(s,e,t){if(!O(e))throw new TypeError("Expected `limit` to be a finite number");if(!O(t))throw new TypeError("Expected `interval` to be a finite number");var r=[],o=[],n=0,i=function(){n++;var a=setTimeout(function(){n--,r.length>0&&i(),o=o.filter(function(u){return u!==a})},t);o.indexOf(a)<0&&o.push(a);var c=r.shift();c.resolve(s.apply(c.self,c.args))},l=function(){var a=arguments,c=this;return new Promise(function(u,p){r.push({resolve:u,reject:p,args:a,self:c}),n<e&&i()})};return l.abort=function(){o.forEach(clearTimeout),o=[],r.forEach(function(a){a.reject(new throttle.AbortError)}),r.length=0},l}E.AbortError=function(){Error.call(this,"Throttled function aborted"),this.name="AbortError"};const D=function(s,e){if(!s)return null;let t={};for(let r in s){let o=s[r];e.indexOf(r)>-1&&o!==null&&(t[r]=o)}return t};var J={nodes:{horizontal_rule:s=>({singleTag:"hr"}),blockquote:s=>({tag:"blockquote"}),bullet_list:s=>({tag:"ul"}),code_block:s=>({tag:["pre",{tag:"code",attrs:s.attrs}]}),hard_break:s=>({singleTag:"br"}),heading:s=>({tag:"h"+s.attrs.level}),image:s=>({singleTag:[{tag:"img",attrs:D(s.attrs,["src","alt","title"])}]}),list_item:s=>({tag:"li"}),ordered_list:s=>({tag:"ol"}),paragraph:s=>({tag:"p"})},marks:{bold:()=>({tag:"b"}),strike:()=>({tag:"strike"}),underline:()=>({tag:"u"}),strong:()=>({tag:"strong"}),code:()=>({tag:"code"}),italic:()=>({tag:"i"}),link(s){const e=f({},s.attrs),{linktype:t="url"}=s.attrs;return t==="email"&&(e.href="mailto:"+e.href),e.anchor&&(e.href=`${e.href}#${e.anchor}`,delete e.anchor),{tag:[{tag:"a",attrs:e}]}},styled:s=>({tag:[{tag:"span",attrs:s.attrs}]})}};class Y{constructor(e){e||(e=J),this.marks=e.marks||[],this.nodes=e.nodes||[]}addNode(e,t){this.nodes[e]=t}addMark(e,t){this.marks[e]=t}render(e={}){if(e.content&&Array.isArray(e.content)){let t="";return e.content.forEach(r=>{t+=this.renderNode(r)}),t}return console.warn("The render method must receive an object with a content field, which is an array"),""}renderNode(e){let t=[];e.marks&&e.marks.forEach(o=>{const n=this.getMatchingMark(o);n&&t.push(this.renderOpeningTag(n.tag))});const r=this.getMatchingNode(e);return r&&r.tag&&t.push(this.renderOpeningTag(r.tag)),e.content?e.content.forEach(o=>{t.push(this.renderNode(o))}):e.text?t.push(function(o){const n={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"},i=/[&<>"']/g,l=RegExp(i.source);return o&&l.test(o)?o.replace(i,a=>n[a]):o}(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(o=>{const n=this.getMatchingMark(o);n&&t.push(this.renderClosingTag(n.tag))}),t.join("")}renderTag(e,t){return e.constructor===String?`<${e}${t}>`:e.map(r=>{if(r.constructor===String)return`<${r}${t}>`;{let o="<"+r.tag;if(r.attrs)for(let n in r.attrs){let i=r.attrs[n];i!==null&&(o+=` ${n}="${i}"`)}return`${o}${t}>`}}).join("")}renderOpeningTag(e){return this.renderTag(e,"")}renderClosingTag(e){return e.constructor===String?`</${e}>`:e.slice(0).reverse().map(t=>t.constructor===String?`</${t}>`:`</${t.tag}>`).join("")}getMatchingNode(e){if(typeof this.nodes[e.type]=="function")return this.nodes[e.type](e)}getMatchingMark(e){if(typeof this.marks[e.type]=="function")return this.marks[e.type](e)}}const F=(s=0,e=s)=>{const t=Math.abs(e-s)||0,r=s<e?1:-1;return((o=0,n)=>[...Array(o)].map(n))(t,(o,n)=>n*r+s)},v=(s,e,t)=>{const r=[];for(const o in s){if(!Object.prototype.hasOwnProperty.call(s,o))continue;const n=s[o],i=t?"":encodeURIComponent(o);let l;l=typeof n=="object"?v(n,e?e+encodeURIComponent("["+i+"]"):i,Array.isArray(n)):(e?e+encodeURIComponent("["+i+"]"):i)+"="+encodeURIComponent(n),r.push(l)}return r.join("&")};let m={},g={};class X{constructor(e,t){if(!t){let n=e.region?"-"+e.region:"",i=e.https===!1?"http":"https";t=e.oauthToken===void 0?`${i}://api${n}.storyblok.com/v2`:`${i}://api${n}.storyblok.com/v1`}let r=Object.assign({},e.headers),o=5;e.oauthToken!==void 0&&(r.Authorization=e.oauthToken,o=3),e.rateLimit!==void 0&&(o=e.rateLimit),this.richTextResolver=new Y(e.richTextSchema),typeof e.componentResolver=="function"&&this.setComponentResolver(e.componentResolver),this.maxRetries=e.maxRetries||5,this.throttle=E(this.throttledRequest,o,1e3),this.accessToken=e.accessToken,this.relations={},this.links={},this.cache=e.cache||{clear:"manual"},this.client=V.default.create({baseURL:t,timeout:e.timeout||0,headers:r,proxy:e.proxy||!1}),e.responseInterceptor&&this.client.interceptors.response.use(n=>e.responseInterceptor(n))}setComponentResolver(e){this.richTextResolver.addNode("blok",t=>{let r="";return t.attrs.body.forEach(o=>{r+=e(o.component,o)}),{html:r}})}parseParams(e={}){return e.version||(e.version="published"),e.token||(e.token=this.getToken()),e.cv||(e.cv=g[e.token]),Array.isArray(e.resolve_relations)&&(e.resolve_relations=e.resolve_relations.join(",")),e}factoryParamOptions(e,t={}){return((r="")=>r.indexOf("/cdn/")>-1)(e)?this.parseParams(t):t}makeRequest(e,t,r,o){const n=this.factoryParamOptions(e,((i={},l=25,a=1)=>k(f({},i),{per_page:l,page:a}))(t,r,o));return this.cacheResponse(e,n)}get(e,t){let r="/"+e;const o=this.factoryParamOptions(r,t);return this.cacheResponse(r,o)}async getAll(e,t={},r){const o=t.per_page||25,n="/"+e,i=n.split("/");r=r||i[i.length-1];const l=await this.makeRequest(n,t,o,1),a=Math.ceil(l.total/o);return((c=[],u)=>c.map(u).reduce((p,d)=>[...p,...d],[]))([l,...await(async(c=[],u)=>Promise.all(c.map(u)))(F(1,a),async c=>this.makeRequest(n,t,o,c+1))],c=>Object.values(c.data[r]))}post(e,t){let r="/"+e;return this.throttle("post",r,t)}put(e,t){let r="/"+e;return this.throttle("put",r,t)}delete(e,t){let r="/"+e;return this.throttle("delete",r,t)}getStories(e){return this.get("cdn/stories",e)}getStory(e,t){return this.get("cdn/stories/"+e,t)}setToken(e){this.accessToken=e}getToken(){return this.accessToken}_cleanCopy(e){return JSON.parse(JSON.stringify(e))}_insertLinks(e,t){const r=e[t];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(e,t,r){if(r.indexOf(e.component+"."+t)>-1){if(typeof e[t]=="string")this.relations[e[t]]&&(e[t]=this._cleanCopy(this.relations[e[t]]));else if(e[t].constructor===Array){let o=[];e[t].forEach(n=>{this.relations[n]&&o.push(this._cleanCopy(this.relations[n]))}),e[t]=o}}}iterateTree(e,t){let r=o=>{if(o!=null){if(o.constructor===Array)for(let n=0;n<o.length;n++)r(o[n]);else if(o.constructor===Object){if(o._stopResolving)return;for(let n in o)(o.component&&o._uid||o.type==="link")&&(this._insertRelations(o,n,t),this._insertLinks(o,n)),r(o[n])}}};r(e.content)}async resolveLinks(e,t){let r=[];if(e.link_uuids){const o=e.link_uuids.length;let n=[];const i=50;for(let l=0;l<o;l+=i){const a=Math.min(o,l+i);n.push(e.link_uuids.slice(l,a))}for(let l=0;l<n.length;l++)(await this.getStories({per_page:i,language:t.language,version:t.version,by_uuids:n[l].join(",")})).data.stories.forEach(a=>{r.push(a)})}else r=e.links;r.forEach(o=>{this.links[o.uuid]=k(f({},o),{_stopResolving:!0})})}async resolveRelations(e,t){let r=[];if(e.rel_uuids){const o=e.rel_uuids.length;let n=[];const i=50;for(let l=0;l<o;l+=i){const a=Math.min(o,l+i);n.push(e.rel_uuids.slice(l,a))}for(let l=0;l<n.length;l++)(await this.getStories({per_page:i,language:t.language,version:t.version,by_uuids:n[l].join(",")})).data.stories.forEach(a=>{r.push(a)})}else r=e.rels;r.forEach(o=>{this.relations[o.uuid]=k(f({},o),{_stopResolving:!0})})}async resolveStories(e,t){let r=[];t.resolve_relations!==void 0&&t.resolve_relations.length>0&&(r=t.resolve_relations.split(","),await this.resolveRelations(e,t)),["1","story","url"].indexOf(t.resolve_links)>-1&&await this.resolveLinks(e,t);for(const o in this.relations)this.iterateTree(this.relations[o],r);e.story?this.iterateTree(e.story,r):e.stories.forEach(o=>{this.iterateTree(o,r)})}cacheResponse(e,t,r){return r===void 0&&(r=0),new Promise(async(o,n)=>{let i=v({url:e,params:t}),l=this.cacheProvider();if(this.cache.clear==="auto"&&t.version==="draft"&&await this.flushCache(),t.version==="published"&&e!="/cdn/spaces/me"){const c=await l.get(i);if(c)return o(c)}try{let c=await this.throttle("get",e,{params:t,paramsSerializer:p=>v(p)}),u={data:c.data,headers:c.headers};if(c.headers["per-page"]&&(u=Object.assign({},u,{perPage:parseInt(c.headers["per-page"]),total:parseInt(c.headers.total)})),c.status!=200)return n(c);(u.data.story||u.data.stories)&&await this.resolveStories(u.data,t),t.version==="published"&&e!="/cdn/spaces/me"&&l.set(i,u),u.data.cv&&(t.version=="draft"&&g[t.token]!=u.data.cv&&this.flushCache(),g[t.token]=u.data.cv),o(u)}catch(c){if(c.response&&c.response.status===429&&(r+=1)<this.maxRetries)return console.log(`Hit rate limit. Retrying in ${r} seconds.`),await(a=1e3*r,new Promise(u=>setTimeout(u,a))),this.cacheResponse(e,t,r).then(o).catch(n);n(c)}var a})}throttledRequest(e,t,r){return this.client[e](t,r)}cacheVersions(){return g}cacheVersion(){return g[this.accessToken]}setCacheVersion(e){this.accessToken&&(g[this.accessToken]=e)}cacheProvider(){switch(this.cache.type){case"memory":return{get:e=>m[e],getAll:()=>m,set(e,t){m[e]=t},flush(){m={}}};default:return{get(){},getAll(){},set(){},flush(){}}}}async flushCache(){return await this.cacheProvider().flush(),this}}var H=(s={})=>{const{apiOptions:e}=s;if(!e.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(e)}},W=s=>{if(typeof s!="object"||typeof s._editable=="undefined")return{};const e=JSON.parse(s._editable.replace(/^<!--#storyblok#/,"").replace(/-->$/,""));return{"data-blok-c":JSON.stringify(e),"data-blok-uid":e.id+"-"+e.uid}};const P=(s,e,t={})=>{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}window.storyblokRegisterEvent(()=>{new window.StoryblokBridge(t).on(["input","published","change"],o=>{o.action=="input"&&o.story.id===s?e(o.story):window.location.reload()})})}},G=(s={})=>{const{bridge:e,accessToken:t,use:r=[],apiOptions:o={}}=s;o.accessToken=o.accessToken||t;const n={bridge:e,apiOptions:o};let i={};return r.forEach(l=>{i=f(f({},i),l(n))}),e!==!1&&z("https://app.storyblok.com/f/storyblok-v2-latest.js"),i};var K=function(){var s=this,e=s.$createElement,t=s._self._c||e;return t(s.blok.component,s._g(s._b({tag:"component"},"component",Object.assign({},s.$props,s.$attrs),!1),s.$listeners))},Q=[];function Z(s,e,t,r,o,n,i,l){var a=typeof s=="function"?s.options:s;e&&(a.render=e,a.staticRenderFns=t,a._compiled=!0),r&&(a.functional=!0),n&&(a._scopeId="data-v-"+n);var c;if(i?(c=function(d){d=d||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,!d&&typeof __VUE_SSR_CONTEXT__!="undefined"&&(d=__VUE_SSR_CONTEXT__),o&&o.call(this,d),d&&d._registeredComponents&&d._registeredComponents.add(i)},a._ssrRegister=c):o&&(c=l?function(){o.call(this,(a.functional?this.parent:this).$root.$options.shadowRoot)}:o),c)if(a.functional){a._injectStyles=c;var u=a.render;a.render=function(ne,I){return c.call(I),u(ne,I)}}else{var p=a.beforeCreate;a.beforeCreate=p?[].concat(p,c):[c]}return{exports:s,options:a}}const ee={props:{blok:{type:Object}}},C={};var te=Z(ee,K,Q,!1,re,null,null,null);function re(s){for(let e in C)this[e]=C[e]}var $=function(){return te.exports}();const j=s=>{console.error(`You can't use ${s} if you're not loading apiPlugin. Please provide it on StoryblokVue initialization.
6
+ `)};var oe=(s,e={},t={})=>{const r=_.ref(null),o=A();return _.onMounted(async()=>{if(o){const{data:n}=await o.get(`cdn/stories/${s}`,e);r.value=n.story}else j("useStoryblok");r.value&&r.value.id&&P(r.value.id,n=>r.value=n,t)}),r};const se={bind(s,e){if(e.value){const t=W(e.value);s.setAttribute("data-blok-c",t["data-blok-c"]),s.setAttribute("data-blok-uid",t["data-blok-uid"]),s.classList.add("storyblok__outline")}}};let b=null;const A=()=>(b||j("useStoryblokApi"),b),M={install(s,e={}){s.directive("editable",se),s.component("StoryblokComponent",$);const{storyblokApi:t}=G(e);b=t,s.prototype.$storyblokApi=t}};typeof window!="undefined"&&window.Vue&&window.Vue.use(M),h.StoryblokComponent=$,h.StoryblokVue=M,h.apiPlugin=H,h.useStoryblok=oe,h.useStoryblokApi=A,h.useStoryblokBridge=P,Object.defineProperty(h,"__esModule",{value:!0}),h[Symbol.toStringTag]="Module"});
@@ -0,0 +1,564 @@
1
+ import t from "axios";
2
+ import { ref, onMounted } from "@vue/composition-api";
3
+ var __defProp = Object.defineProperty;
4
+ var __defProps = Object.defineProperties;
5
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
6
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
9
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
10
+ var __spreadValues = (a2, b) => {
11
+ for (var prop in b || (b = {}))
12
+ if (__hasOwnProp.call(b, prop))
13
+ __defNormalProp(a2, prop, b[prop]);
14
+ if (__getOwnPropSymbols)
15
+ for (var prop of __getOwnPropSymbols(b)) {
16
+ if (__propIsEnum.call(b, prop))
17
+ __defNormalProp(a2, prop, b[prop]);
18
+ }
19
+ return a2;
20
+ };
21
+ var __spreadProps = (a2, b) => __defProps(a2, __getOwnPropDescs(b));
22
+ let loaded = false;
23
+ const callbacks = [];
24
+ const loadBridge = (src) => {
25
+ return new Promise((resolve, reject) => {
26
+ if (typeof window === "undefined")
27
+ return;
28
+ window.storyblokRegisterEvent = (cb) => {
29
+ if (window.location === window.parent.location) {
30
+ console.warn("You are not in Draft Mode or in the Visual Editor.");
31
+ return;
32
+ }
33
+ if (!loaded)
34
+ callbacks.push(cb);
35
+ else
36
+ cb();
37
+ };
38
+ if (document.getElementById("storyblok-javascript-bridge"))
39
+ return;
40
+ const script = document.createElement("script");
41
+ script.async = true;
42
+ script.src = src;
43
+ script.id = "storyblok-javascript-bridge";
44
+ script.onerror = (error) => reject(error);
45
+ script.onload = (ev) => {
46
+ callbacks.forEach((cb) => cb());
47
+ loaded = true;
48
+ resolve(ev);
49
+ };
50
+ document.getElementsByTagName("head")[0].appendChild(script);
51
+ });
52
+ };
53
+ /*!
54
+ * storyblok-js-client v0.0.0-development
55
+ * Universal JavaScript SDK for Storyblok's API
56
+ * (c) 2020-2022 Stobylok Team
57
+ */
58
+ function e(t2) {
59
+ return typeof t2 == "number" && (t2 == t2 && t2 !== 1 / 0 && t2 !== -1 / 0);
60
+ }
61
+ function r(t2, r2, s2) {
62
+ if (!e(r2))
63
+ throw new TypeError("Expected `limit` to be a finite number");
64
+ if (!e(s2))
65
+ throw new TypeError("Expected `interval` to be a finite number");
66
+ var n2 = [], i2 = [], o2 = 0, a2 = function() {
67
+ o2++;
68
+ var e2 = setTimeout(function() {
69
+ o2--, n2.length > 0 && a2(), i2 = i2.filter(function(t3) {
70
+ return t3 !== e2;
71
+ });
72
+ }, s2);
73
+ i2.indexOf(e2) < 0 && i2.push(e2);
74
+ var r3 = n2.shift();
75
+ r3.resolve(t2.apply(r3.self, r3.args));
76
+ }, l2 = function() {
77
+ var t3 = arguments, e2 = this;
78
+ return new Promise(function(s3, i3) {
79
+ n2.push({ resolve: s3, reject: i3, args: t3, self: e2 }), o2 < r2 && a2();
80
+ });
81
+ };
82
+ return l2.abort = function() {
83
+ i2.forEach(clearTimeout), i2 = [], n2.forEach(function(t3) {
84
+ t3.reject(new throttle.AbortError());
85
+ }), n2.length = 0;
86
+ }, l2;
87
+ }
88
+ r.AbortError = function() {
89
+ Error.call(this, "Throttled function aborted"), this.name = "AbortError";
90
+ };
91
+ const s = function(t2, e2) {
92
+ if (!t2)
93
+ return null;
94
+ let r2 = {};
95
+ for (let s2 in t2) {
96
+ let n2 = t2[s2];
97
+ e2.indexOf(s2) > -1 && n2 !== null && (r2[s2] = n2);
98
+ }
99
+ return r2;
100
+ };
101
+ var n = { nodes: { horizontal_rule: (t2) => ({ singleTag: "hr" }), blockquote: (t2) => ({ tag: "blockquote" }), bullet_list: (t2) => ({ tag: "ul" }), code_block: (t2) => ({ tag: ["pre", { tag: "code", attrs: t2.attrs }] }), hard_break: (t2) => ({ singleTag: "br" }), heading: (t2) => ({ tag: "h" + t2.attrs.level }), image: (t2) => ({ singleTag: [{ tag: "img", attrs: s(t2.attrs, ["src", "alt", "title"]) }] }), list_item: (t2) => ({ tag: "li" }), ordered_list: (t2) => ({ tag: "ol" }), paragraph: (t2) => ({ tag: "p" }) }, marks: { bold: () => ({ tag: "b" }), strike: () => ({ tag: "strike" }), underline: () => ({ tag: "u" }), strong: () => ({ tag: "strong" }), code: () => ({ tag: "code" }), italic: () => ({ tag: "i" }), link(t2) {
102
+ const e2 = __spreadValues({}, t2.attrs), { linktype: r2 = "url" } = t2.attrs;
103
+ return r2 === "email" && (e2.href = "mailto:" + e2.href), e2.anchor && (e2.href = `${e2.href}#${e2.anchor}`, delete e2.anchor), { tag: [{ tag: "a", attrs: e2 }] };
104
+ }, styled: (t2) => ({ tag: [{ tag: "span", attrs: t2.attrs }] }) } };
105
+ class i {
106
+ constructor(t2) {
107
+ t2 || (t2 = n), this.marks = t2.marks || [], this.nodes = t2.nodes || [];
108
+ }
109
+ addNode(t2, e2) {
110
+ this.nodes[t2] = e2;
111
+ }
112
+ addMark(t2, e2) {
113
+ this.marks[t2] = e2;
114
+ }
115
+ render(t2 = {}) {
116
+ if (t2.content && Array.isArray(t2.content)) {
117
+ let e2 = "";
118
+ return t2.content.forEach((t3) => {
119
+ e2 += this.renderNode(t3);
120
+ }), e2;
121
+ }
122
+ return console.warn("The render method must receive an object with a content field, which is an array"), "";
123
+ }
124
+ renderNode(t2) {
125
+ let e2 = [];
126
+ t2.marks && t2.marks.forEach((t3) => {
127
+ const r3 = this.getMatchingMark(t3);
128
+ r3 && e2.push(this.renderOpeningTag(r3.tag));
129
+ });
130
+ const r2 = this.getMatchingNode(t2);
131
+ return r2 && r2.tag && e2.push(this.renderOpeningTag(r2.tag)), t2.content ? t2.content.forEach((t3) => {
132
+ e2.push(this.renderNode(t3));
133
+ }) : t2.text ? e2.push(function(t3) {
134
+ const e3 = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }, r3 = /[&<>"']/g, s2 = RegExp(r3.source);
135
+ return t3 && s2.test(t3) ? t3.replace(r3, (t4) => e3[t4]) : t3;
136
+ }(t2.text)) : r2 && r2.singleTag ? e2.push(this.renderTag(r2.singleTag, " /")) : r2 && r2.html && e2.push(r2.html), r2 && r2.tag && e2.push(this.renderClosingTag(r2.tag)), t2.marks && t2.marks.slice(0).reverse().forEach((t3) => {
137
+ const r3 = this.getMatchingMark(t3);
138
+ r3 && e2.push(this.renderClosingTag(r3.tag));
139
+ }), e2.join("");
140
+ }
141
+ renderTag(t2, e2) {
142
+ if (t2.constructor === String)
143
+ return `<${t2}${e2}>`;
144
+ return t2.map((t3) => {
145
+ if (t3.constructor === String)
146
+ return `<${t3}${e2}>`;
147
+ {
148
+ let r2 = "<" + t3.tag;
149
+ if (t3.attrs)
150
+ for (let e3 in t3.attrs) {
151
+ let s2 = t3.attrs[e3];
152
+ s2 !== null && (r2 += ` ${e3}="${s2}"`);
153
+ }
154
+ return `${r2}${e2}>`;
155
+ }
156
+ }).join("");
157
+ }
158
+ renderOpeningTag(t2) {
159
+ return this.renderTag(t2, "");
160
+ }
161
+ renderClosingTag(t2) {
162
+ if (t2.constructor === String)
163
+ return `</${t2}>`;
164
+ return t2.slice(0).reverse().map((t3) => t3.constructor === String ? `</${t3}>` : `</${t3.tag}>`).join("");
165
+ }
166
+ getMatchingNode(t2) {
167
+ if (typeof this.nodes[t2.type] == "function")
168
+ return this.nodes[t2.type](t2);
169
+ }
170
+ getMatchingMark(t2) {
171
+ if (typeof this.marks[t2.type] == "function")
172
+ return this.marks[t2.type](t2);
173
+ }
174
+ }
175
+ const o = (t2 = 0, e2 = t2) => {
176
+ const r2 = Math.abs(e2 - t2) || 0, s2 = t2 < e2 ? 1 : -1;
177
+ return ((t3 = 0, e3) => [...Array(t3)].map(e3))(r2, (e3, r3) => r3 * s2 + t2);
178
+ }, a = (t2, e2, r2) => {
179
+ const s2 = [];
180
+ for (const n2 in t2) {
181
+ if (!Object.prototype.hasOwnProperty.call(t2, n2))
182
+ continue;
183
+ const i2 = t2[n2], o2 = r2 ? "" : encodeURIComponent(n2);
184
+ let l2;
185
+ l2 = typeof i2 == "object" ? a(i2, e2 ? e2 + encodeURIComponent("[" + o2 + "]") : o2, Array.isArray(i2)) : (e2 ? e2 + encodeURIComponent("[" + o2 + "]") : o2) + "=" + encodeURIComponent(i2), s2.push(l2);
186
+ }
187
+ return s2.join("&");
188
+ };
189
+ let l = {}, c = {};
190
+ class StoryblokClient {
191
+ constructor(e2, s2) {
192
+ if (!s2) {
193
+ let t2 = e2.region ? "-" + e2.region : "", r2 = e2.https === false ? "http" : "https";
194
+ s2 = e2.oauthToken === void 0 ? `${r2}://api${t2}.storyblok.com/v2` : `${r2}://api${t2}.storyblok.com/v1`;
195
+ }
196
+ let n2 = Object.assign({}, e2.headers), o2 = 5;
197
+ e2.oauthToken !== void 0 && (n2.Authorization = e2.oauthToken, o2 = 3), e2.rateLimit !== void 0 && (o2 = e2.rateLimit), this.richTextResolver = new i(e2.richTextSchema), typeof e2.componentResolver == "function" && this.setComponentResolver(e2.componentResolver), this.maxRetries = e2.maxRetries || 5, this.throttle = r(this.throttledRequest, o2, 1e3), this.accessToken = e2.accessToken, this.relations = {}, this.links = {}, this.cache = e2.cache || { clear: "manual" }, this.client = t.create({ baseURL: s2, timeout: e2.timeout || 0, headers: n2, proxy: e2.proxy || false }), e2.responseInterceptor && this.client.interceptors.response.use((t2) => e2.responseInterceptor(t2));
198
+ }
199
+ setComponentResolver(t2) {
200
+ this.richTextResolver.addNode("blok", (e2) => {
201
+ let r2 = "";
202
+ return e2.attrs.body.forEach((e3) => {
203
+ r2 += t2(e3.component, e3);
204
+ }), { html: r2 };
205
+ });
206
+ }
207
+ parseParams(t2 = {}) {
208
+ return t2.version || (t2.version = "published"), t2.token || (t2.token = this.getToken()), t2.cv || (t2.cv = c[t2.token]), Array.isArray(t2.resolve_relations) && (t2.resolve_relations = t2.resolve_relations.join(",")), t2;
209
+ }
210
+ factoryParamOptions(t2, e2 = {}) {
211
+ return ((t3 = "") => t3.indexOf("/cdn/") > -1)(t2) ? this.parseParams(e2) : e2;
212
+ }
213
+ makeRequest(t2, e2, r2, s2) {
214
+ const n2 = this.factoryParamOptions(t2, ((t3 = {}, e3 = 25, r3 = 1) => __spreadProps(__spreadValues({}, t3), { per_page: e3, page: r3 }))(e2, r2, s2));
215
+ return this.cacheResponse(t2, n2);
216
+ }
217
+ get(t2, e2) {
218
+ let r2 = "/" + t2;
219
+ const s2 = this.factoryParamOptions(r2, e2);
220
+ return this.cacheResponse(r2, s2);
221
+ }
222
+ async getAll(t2, e2 = {}, r2) {
223
+ const s2 = e2.per_page || 25, n2 = "/" + t2, i2 = n2.split("/");
224
+ r2 = r2 || i2[i2.length - 1];
225
+ const a2 = await this.makeRequest(n2, e2, s2, 1), l2 = Math.ceil(a2.total / s2);
226
+ return ((t3 = [], e3) => t3.map(e3).reduce((t4, e4) => [...t4, ...e4], []))([a2, ...await (async (t3 = [], e3) => Promise.all(t3.map(e3)))(o(1, l2), async (t3) => this.makeRequest(n2, e2, s2, t3 + 1))], (t3) => Object.values(t3.data[r2]));
227
+ }
228
+ post(t2, e2) {
229
+ let r2 = "/" + t2;
230
+ return this.throttle("post", r2, e2);
231
+ }
232
+ put(t2, e2) {
233
+ let r2 = "/" + t2;
234
+ return this.throttle("put", r2, e2);
235
+ }
236
+ delete(t2, e2) {
237
+ let r2 = "/" + t2;
238
+ return this.throttle("delete", r2, e2);
239
+ }
240
+ getStories(t2) {
241
+ return this.get("cdn/stories", t2);
242
+ }
243
+ getStory(t2, e2) {
244
+ return this.get("cdn/stories/" + t2, e2);
245
+ }
246
+ setToken(t2) {
247
+ this.accessToken = t2;
248
+ }
249
+ getToken() {
250
+ return this.accessToken;
251
+ }
252
+ _cleanCopy(t2) {
253
+ return JSON.parse(JSON.stringify(t2));
254
+ }
255
+ _insertLinks(t2, e2) {
256
+ const r2 = t2[e2];
257
+ r2 && r2.fieldtype == "multilink" && r2.linktype == "story" && typeof r2.id == "string" && this.links[r2.id] ? r2.story = this._cleanCopy(this.links[r2.id]) : r2 && r2.linktype === "story" && typeof r2.uuid == "string" && this.links[r2.uuid] && (r2.story = this._cleanCopy(this.links[r2.uuid]));
258
+ }
259
+ _insertRelations(t2, e2, r2) {
260
+ if (r2.indexOf(t2.component + "." + e2) > -1) {
261
+ if (typeof t2[e2] == "string")
262
+ this.relations[t2[e2]] && (t2[e2] = this._cleanCopy(this.relations[t2[e2]]));
263
+ else if (t2[e2].constructor === Array) {
264
+ let r3 = [];
265
+ t2[e2].forEach((t3) => {
266
+ this.relations[t3] && r3.push(this._cleanCopy(this.relations[t3]));
267
+ }), t2[e2] = r3;
268
+ }
269
+ }
270
+ }
271
+ iterateTree(t2, e2) {
272
+ let r2 = (t3) => {
273
+ if (t3 != null) {
274
+ if (t3.constructor === Array)
275
+ for (let e3 = 0; e3 < t3.length; e3++)
276
+ r2(t3[e3]);
277
+ else if (t3.constructor === Object) {
278
+ if (t3._stopResolving)
279
+ return;
280
+ for (let s2 in t3)
281
+ (t3.component && t3._uid || t3.type === "link") && (this._insertRelations(t3, s2, e2), this._insertLinks(t3, s2)), r2(t3[s2]);
282
+ }
283
+ }
284
+ };
285
+ r2(t2.content);
286
+ }
287
+ async resolveLinks(t2, e2) {
288
+ let r2 = [];
289
+ if (t2.link_uuids) {
290
+ const s2 = t2.link_uuids.length;
291
+ let n2 = [];
292
+ const i2 = 50;
293
+ for (let e3 = 0; e3 < s2; e3 += i2) {
294
+ const r3 = Math.min(s2, e3 + i2);
295
+ n2.push(t2.link_uuids.slice(e3, r3));
296
+ }
297
+ for (let t3 = 0; t3 < n2.length; t3++) {
298
+ (await this.getStories({ per_page: i2, language: e2.language, version: e2.version, by_uuids: n2[t3].join(",") })).data.stories.forEach((t4) => {
299
+ r2.push(t4);
300
+ });
301
+ }
302
+ } else
303
+ r2 = t2.links;
304
+ r2.forEach((t3) => {
305
+ this.links[t3.uuid] = __spreadProps(__spreadValues({}, t3), { _stopResolving: true });
306
+ });
307
+ }
308
+ async resolveRelations(t2, e2) {
309
+ let r2 = [];
310
+ if (t2.rel_uuids) {
311
+ const s2 = t2.rel_uuids.length;
312
+ let n2 = [];
313
+ const i2 = 50;
314
+ for (let e3 = 0; e3 < s2; e3 += i2) {
315
+ const r3 = Math.min(s2, e3 + i2);
316
+ n2.push(t2.rel_uuids.slice(e3, r3));
317
+ }
318
+ for (let t3 = 0; t3 < n2.length; t3++) {
319
+ (await this.getStories({ per_page: i2, language: e2.language, version: e2.version, by_uuids: n2[t3].join(",") })).data.stories.forEach((t4) => {
320
+ r2.push(t4);
321
+ });
322
+ }
323
+ } else
324
+ r2 = t2.rels;
325
+ r2.forEach((t3) => {
326
+ this.relations[t3.uuid] = __spreadProps(__spreadValues({}, t3), { _stopResolving: true });
327
+ });
328
+ }
329
+ async resolveStories(t2, e2) {
330
+ let r2 = [];
331
+ e2.resolve_relations !== void 0 && e2.resolve_relations.length > 0 && (r2 = e2.resolve_relations.split(","), await this.resolveRelations(t2, e2)), ["1", "story", "url"].indexOf(e2.resolve_links) > -1 && await this.resolveLinks(t2, e2);
332
+ for (const t3 in this.relations)
333
+ this.iterateTree(this.relations[t3], r2);
334
+ t2.story ? this.iterateTree(t2.story, r2) : t2.stories.forEach((t3) => {
335
+ this.iterateTree(t3, r2);
336
+ });
337
+ }
338
+ cacheResponse(t2, e2, r2) {
339
+ return r2 === void 0 && (r2 = 0), new Promise(async (s2, n2) => {
340
+ let i2 = a({ url: t2, params: e2 }), o2 = this.cacheProvider();
341
+ if (this.cache.clear === "auto" && e2.version === "draft" && await this.flushCache(), e2.version === "published" && t2 != "/cdn/spaces/me") {
342
+ const t3 = await o2.get(i2);
343
+ if (t3)
344
+ return s2(t3);
345
+ }
346
+ try {
347
+ let r3 = await this.throttle("get", t2, { params: e2, paramsSerializer: (t3) => a(t3) }), l3 = { data: r3.data, headers: r3.headers };
348
+ if (r3.headers["per-page"] && (l3 = Object.assign({}, l3, { perPage: parseInt(r3.headers["per-page"]), total: parseInt(r3.headers.total) })), r3.status != 200)
349
+ return n2(r3);
350
+ (l3.data.story || l3.data.stories) && await this.resolveStories(l3.data, e2), e2.version === "published" && t2 != "/cdn/spaces/me" && o2.set(i2, l3), l3.data.cv && (e2.version == "draft" && c[e2.token] != l3.data.cv && this.flushCache(), c[e2.token] = l3.data.cv), s2(l3);
351
+ } catch (i3) {
352
+ if (i3.response && i3.response.status === 429 && (r2 += 1) < this.maxRetries)
353
+ return console.log(`Hit rate limit. Retrying in ${r2} seconds.`), await (l2 = 1e3 * r2, new Promise((t3) => setTimeout(t3, l2))), this.cacheResponse(t2, e2, r2).then(s2).catch(n2);
354
+ n2(i3);
355
+ }
356
+ var l2;
357
+ });
358
+ }
359
+ throttledRequest(t2, e2, r2) {
360
+ return this.client[t2](e2, r2);
361
+ }
362
+ cacheVersions() {
363
+ return c;
364
+ }
365
+ cacheVersion() {
366
+ return c[this.accessToken];
367
+ }
368
+ setCacheVersion(t2) {
369
+ this.accessToken && (c[this.accessToken] = t2);
370
+ }
371
+ cacheProvider() {
372
+ switch (this.cache.type) {
373
+ case "memory":
374
+ return { get: (t2) => l[t2], getAll: () => l, set(t2, e2) {
375
+ l[t2] = e2;
376
+ }, flush() {
377
+ l = {};
378
+ } };
379
+ default:
380
+ return { get() {
381
+ }, getAll() {
382
+ }, set() {
383
+ }, flush() {
384
+ } };
385
+ }
386
+ }
387
+ async flushCache() {
388
+ return await this.cacheProvider().flush(), this;
389
+ }
390
+ }
391
+ var api = (options = {}) => {
392
+ const { apiOptions } = options;
393
+ if (!apiOptions.accessToken) {
394
+ 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");
395
+ return;
396
+ }
397
+ const storyblokApi = new StoryblokClient(apiOptions);
398
+ return { storyblokApi };
399
+ };
400
+ var editable = (blok) => {
401
+ if (typeof blok !== "object" || typeof blok._editable === "undefined") {
402
+ return {};
403
+ }
404
+ const options = JSON.parse(blok._editable.replace(/^<!--#storyblok#/, "").replace(/-->$/, ""));
405
+ return {
406
+ "data-blok-c": JSON.stringify(options),
407
+ "data-blok-uid": options.id + "-" + options.uid
408
+ };
409
+ };
410
+ const useStoryblokBridge = (id, cb, options = {}) => {
411
+ if (typeof window === "undefined") {
412
+ return;
413
+ }
414
+ if (typeof window.storyblokRegisterEvent === "undefined") {
415
+ console.error("Storyblok Bridge is disabled. Please enable it to use it. Read https://github.com/storyblok/storyblok-js");
416
+ return;
417
+ }
418
+ window.storyblokRegisterEvent(() => {
419
+ const sbBridge = new window.StoryblokBridge(options);
420
+ sbBridge.on(["input", "published", "change"], (event) => {
421
+ if (event.action == "input" && event.story.id === id) {
422
+ cb(event.story);
423
+ } else {
424
+ window.location.reload();
425
+ }
426
+ });
427
+ });
428
+ };
429
+ const storyblokInit = (pluginOptions = {}) => {
430
+ const { bridge, accessToken, use = [], apiOptions = {} } = pluginOptions;
431
+ apiOptions.accessToken = apiOptions.accessToken || accessToken;
432
+ const options = { bridge, apiOptions };
433
+ let result = {};
434
+ use.forEach((pluginFactory) => {
435
+ result = __spreadValues(__spreadValues({}, result), pluginFactory(options));
436
+ });
437
+ if (bridge !== false) {
438
+ loadBridge("https://app.storyblok.com/f/storyblok-v2-latest.js");
439
+ }
440
+ return result;
441
+ };
442
+ var render = function() {
443
+ var _vm = this;
444
+ var _h = _vm.$createElement;
445
+ var _c = _vm._self._c || _h;
446
+ return _c(_vm.blok.component, _vm._g(_vm._b({ tag: "component" }, "component", Object.assign({}, _vm.$props, _vm.$attrs), false), _vm.$listeners));
447
+ };
448
+ var staticRenderFns = [];
449
+ function normalizeComponent(scriptExports, render2, staticRenderFns2, functionalTemplate, injectStyles, scopeId, moduleIdentifier, shadowMode) {
450
+ var options = typeof scriptExports === "function" ? scriptExports.options : scriptExports;
451
+ if (render2) {
452
+ options.render = render2;
453
+ options.staticRenderFns = staticRenderFns2;
454
+ options._compiled = true;
455
+ }
456
+ if (functionalTemplate) {
457
+ options.functional = true;
458
+ }
459
+ if (scopeId) {
460
+ options._scopeId = "data-v-" + scopeId;
461
+ }
462
+ var hook;
463
+ if (moduleIdentifier) {
464
+ hook = function(context) {
465
+ context = context || this.$vnode && this.$vnode.ssrContext || this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext;
466
+ if (!context && typeof __VUE_SSR_CONTEXT__ !== "undefined") {
467
+ context = __VUE_SSR_CONTEXT__;
468
+ }
469
+ if (injectStyles) {
470
+ injectStyles.call(this, context);
471
+ }
472
+ if (context && context._registeredComponents) {
473
+ context._registeredComponents.add(moduleIdentifier);
474
+ }
475
+ };
476
+ options._ssrRegister = hook;
477
+ } else if (injectStyles) {
478
+ hook = shadowMode ? function() {
479
+ injectStyles.call(this, (options.functional ? this.parent : this).$root.$options.shadowRoot);
480
+ } : injectStyles;
481
+ }
482
+ if (hook) {
483
+ if (options.functional) {
484
+ options._injectStyles = hook;
485
+ var originalRender = options.render;
486
+ options.render = function renderWithStyleInjection(h, context) {
487
+ hook.call(context);
488
+ return originalRender(h, context);
489
+ };
490
+ } else {
491
+ var existing = options.beforeCreate;
492
+ options.beforeCreate = existing ? [].concat(existing, hook) : [hook];
493
+ }
494
+ }
495
+ return {
496
+ exports: scriptExports,
497
+ options
498
+ };
499
+ }
500
+ const __vue2_script = {
501
+ props: {
502
+ blok: {
503
+ type: Object
504
+ }
505
+ }
506
+ };
507
+ const __cssModules = {};
508
+ var __component__ = /* @__PURE__ */ normalizeComponent(__vue2_script, render, staticRenderFns, false, __vue2_injectStyles, null, null, null);
509
+ function __vue2_injectStyles(context) {
510
+ for (let o2 in __cssModules) {
511
+ this[o2] = __cssModules[o2];
512
+ }
513
+ }
514
+ var StoryblokComponent = /* @__PURE__ */ function() {
515
+ return __component__.exports;
516
+ }();
517
+ const printError = (fnName) => {
518
+ console.error(`You can't use ${fnName} if you're not loading apiPlugin. Please provide it on StoryblokVue initialization.
519
+ `);
520
+ };
521
+ var useStoryblok = (url, apiOptions = {}, bridgeOptions = {}) => {
522
+ const story = ref(null);
523
+ const storyblokApiInstance2 = useStoryblokApi();
524
+ onMounted(async () => {
525
+ if (storyblokApiInstance2) {
526
+ const { data } = await storyblokApiInstance2.get(`cdn/stories/${url}`, apiOptions);
527
+ story.value = data.story;
528
+ } else
529
+ printError("useStoryblok");
530
+ if (story.value && story.value.id) {
531
+ useStoryblokBridge(story.value.id, (evStory) => story.value = evStory, bridgeOptions);
532
+ }
533
+ });
534
+ return story;
535
+ };
536
+ const vEditableDirective = {
537
+ bind(el, binding) {
538
+ if (binding.value) {
539
+ const options = editable(binding.value);
540
+ el.setAttribute("data-blok-c", options["data-blok-c"]);
541
+ el.setAttribute("data-blok-uid", options["data-blok-uid"]);
542
+ el.classList.add("storyblok__outline");
543
+ }
544
+ }
545
+ };
546
+ let storyblokApiInstance = null;
547
+ const useStoryblokApi = () => {
548
+ if (!storyblokApiInstance)
549
+ printError("useStoryblokApi");
550
+ return storyblokApiInstance;
551
+ };
552
+ const StoryblokVue = {
553
+ install(app, pluginOptions = {}) {
554
+ app.directive("editable", vEditableDirective);
555
+ app.component("StoryblokComponent", StoryblokComponent);
556
+ const { storyblokApi } = storyblokInit(pluginOptions);
557
+ storyblokApiInstance = storyblokApi;
558
+ app.prototype.$storyblokApi = storyblokApi;
559
+ }
560
+ };
561
+ if (typeof window !== "undefined" && window.Vue) {
562
+ window.Vue.use(StoryblokVue);
563
+ }
564
+ export { StoryblokComponent, StoryblokVue, api as apiPlugin, useStoryblok, useStoryblokApi, useStoryblokBridge };
@@ -0,0 +1,34 @@
1
+ const path = require("path");
2
+
3
+ module.exports = function nuxtStoryblok(moduleOptions) {
4
+ let options = Object.assign({}, this.options.storyblok, moduleOptions);
5
+ this.addPlugin({
6
+ src: path.resolve(__dirname, "plugin.js"),
7
+ options,
8
+ });
9
+
10
+ const nuxtConfig = this.nuxt.options;
11
+ const componentsPath = "~/components/storyblok";
12
+ if (Array.isArray(nuxtConfig.components))
13
+ nuxtConfig.components.push(componentsPath);
14
+ else nuxtConfig.components = [componentsPath];
15
+
16
+ // Disable Webpack 4 mjs support (has issues)
17
+ this.extendBuild((config) => {
18
+ if (!config.module) return;
19
+
20
+ config.module.rules.forEach((rule) => {
21
+ if (rule.test instanceof RegExp && rule.test.test("index.mjs")) {
22
+ rule.type = "javascript/auto";
23
+ }
24
+ });
25
+
26
+ config.module.rules.unshift({
27
+ test: /\.mjs$/,
28
+ type: "javascript/auto",
29
+ include: [/node_modules/],
30
+ });
31
+ });
32
+ };
33
+
34
+ module.exports.meta = require("../package.json");
@@ -0,0 +1,29 @@
1
+ /* eslint-disable */
2
+
3
+ import Vue from 'vue'
4
+ import { StoryblokVue, useStoryblokApi, useStoryblokBridge } from "@storyblok/nuxt";
5
+ <% if (options.useApiClient !== false) { %>
6
+ import { apiPlugin } from "@storyblok/nuxt";
7
+ <% } %>
8
+
9
+ export default (ctx) => {
10
+ const { app, store } = ctx
11
+
12
+ Vue.use(StoryblokVue, {
13
+ accessToken: "<%= options.accessToken %>",
14
+ bridge: <%= 'process.env.NODE_ENV !== "production"' %>,
15
+ apiOptions: <%- JSON.stringify(options.apiOptions || {}) %>,
16
+ <% if (options.useApiClient !== false) { %>
17
+ use: [apiPlugin]
18
+ <% } %>
19
+ });
20
+
21
+ const api = useStoryblokApi()
22
+
23
+ app.$storyapi = api
24
+ ctx.$storyapi = api
25
+ app.$storybridge = useStoryblokBridge
26
+ ctx.$storybridge = useStoryblokBridge
27
+
28
+ if (store) store.$storyapi = api
29
+ }
package/package.json CHANGED
@@ -1,16 +1,22 @@
1
1
  {
2
2
  "name": "@storyblok/nuxt",
3
- "version": "2.0.5",
3
+ "version": "2.1.0",
4
4
  "description": "Storyblok Nuxt.js module",
5
- "license": "MIT",
6
- "contributors": [
7
- {
8
- "name": "Alexander Feiglstorfer <delooks@gmail.com>"
9
- }
5
+ "exports": {
6
+ ".": {
7
+ "import": "./dist/storyblok-nuxt.mjs",
8
+ "require": "./dist/storyblok-nuxt.js"
9
+ },
10
+ "./module": "./module/index.js"
11
+ },
12
+ "main": "./dist/storyblok-nuxt.js",
13
+ "module": "./dist/storyblok-nuxt.mjs",
14
+ "files": [
15
+ "dist",
16
+ "module"
10
17
  ],
11
- "main": "./module.js",
12
- "repository": "https://github.com/storyblok/storyblok-nuxt",
13
18
  "scripts": {
19
+ "build": "vite build",
14
20
  "cy:open": "cypress open",
15
21
  "cy:run": "cypress run",
16
22
  "playground:run": "cd ../playground && npm run start",
@@ -19,13 +25,8 @@
19
25
  "test:e2e-watch": "start-server-and-test playground:run http://localhost:3000 cy:open",
20
26
  "prepublishOnly": "cp ../README.md ./"
21
27
  },
22
- "files": [
23
- "module.js",
24
- "templates"
25
- ],
26
28
  "dependencies": {
27
- "@storyblok/vue": "^2.0.0",
28
- "storyblok-js-client": "^4.1.5"
29
+ "@storyblok/vue-2": "^1.0.2"
29
30
  },
30
31
  "devDependencies": {
31
32
  "@babel/core": "^7.15.0",
@@ -33,21 +34,18 @@
33
34
  "cypress": "^8.3.0",
34
35
  "eslint-plugin-cypress": "^2.12.1",
35
36
  "jest": "^26.6.3",
36
- "start-server-and-test": "^1.14.0"
37
- },
38
- "eslintConfig": {
39
- "env": {
40
- "node": true
41
- }
37
+ "start-server-and-test": "^1.14.0",
38
+ "vite": "^2.8.4"
42
39
  },
43
40
  "release": {
44
41
  "branches": [
45
- "master",
46
- {
47
- "name": "next",
48
- "channel": "next",
49
- "prerelease": "beta"
50
- }
42
+ "main"
51
43
  ]
52
- }
44
+ },
45
+ "repository": "https://github.com/storyblok/storyblok-nuxt",
46
+ "contributors": [
47
+ {
48
+ "name": "Alexander Feiglstorfer <delooks@gmail.com>"
49
+ }
50
+ ]
53
51
  }
package/module.js DELETED
@@ -1,12 +0,0 @@
1
- const path = require("path");
2
-
3
- module.exports = function nuxtStoryblok(moduleOptions) {
4
- let options = Object.assign({}, this.options.storyblok, moduleOptions);
5
-
6
- this.addPlugin({
7
- src: path.resolve(__dirname, "templates/plugin.js"),
8
- options,
9
- });
10
- };
11
-
12
- module.exports.meta = require("./package.json");
@@ -1,82 +0,0 @@
1
- import Vue from 'vue'
2
- import StoryblokClient from 'storyblok-js-client'
3
- import StoryblokVue from '@storyblok/vue'
4
-
5
- const loadScript = function(src, cb) {
6
- if (document.getElementById('storyblok-javascript-bridge')) {
7
- return cb()
8
- }
9
-
10
- var script = document.createElement('script')
11
- script.async = true
12
- script.src = src
13
- script.id = 'storyblok-javascript-bridge'
14
-
15
- script.onerror = function() {
16
- cb(new Error('Failed to load' + src))
17
- }
18
-
19
- script.onload = function() {
20
- cb()
21
- }
22
-
23
- document.getElementsByTagName('head')[0].appendChild(script)
24
- }
25
-
26
- let doLoadScript = true
27
-
28
- const Client = {
29
- install () {
30
- if (!Vue.prototype.$storyapi) {
31
- Vue.prototype.$storyapi = new StoryblokClient({
32
- accessToken: '<%= options.accessToken %>',
33
- cache: {
34
- clear: 'auto',
35
- type: '<%= options.cacheProvider || 'memory' %>'
36
- },
37
- timeout: <%= options.timeout || 0 %><% if (options.region) { %>,
38
- region: '<%= options.region %>'<% } %><% if (typeof options.https !== 'undefined') { %>,
39
- https: <%= options.https %><% } %>
40
- }<% if (typeof options.endpoint !== 'undefined') { %>, '<%= options.endpoint %>'<% } %>)
41
-
42
- Vue.prototype.$storybridge = function(cb, errorCb) {
43
- if (typeof errorCb !== 'function') {
44
- errorCb = function() {}
45
- }
46
-
47
- if (window.location == window.parent.location) {
48
- errorCb('You are not in the edit mode.')
49
- return
50
- }
51
-
52
- if (!doLoadScript) {
53
- if (!window.StoryblokBridge) {
54
- errorCb('The Storyblok bridge script is already loading.')
55
- return
56
- }
57
- cb()
58
- return
59
- }
60
-
61
- doLoadScript = false
62
- loadScript('https://app.storyblok.com/f/storyblok-v2-latest.js', cb)
63
- }
64
- }
65
- }
66
- }
67
-
68
- Vue.use(Client)
69
- Vue.use(StoryblokVue)
70
-
71
- export default (ctx) => {
72
- const { app, store } = ctx
73
-
74
- app.$storyapi = Vue.prototype.$storyapi
75
- ctx.$storyapi = Vue.prototype.$storyapi
76
- app.$storybridge = Vue.prototype.$storybridge
77
- ctx.$storybridge = Vue.prototype.$storybridge
78
-
79
- if (store) {
80
- store.$storyapi = Vue.prototype.$storyapi
81
- }
82
- }