Skip to content

Commit

Permalink
feat: allow bridge configuration from astroconfig file
Browse files Browse the repository at this point in the history
  • Loading branch information
dipankarmaikap committed Sep 17, 2024
1 parent c555207 commit 9d7a619
Show file tree
Hide file tree
Showing 11 changed files with 247 additions and 275 deletions.
42 changes: 28 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,33 +375,47 @@ export default defineConfig({
});
```
2. Additionally, please use `useStoryblok` on your Astro pages for story fetching. This replaces the previously used `useStoryblokApi` method.
1. Additionally, please use `getLiveStory` on your Astro pages for getting live story.
```jsx
//pages/[...slug].astro
---
import { useStoryblok } from "@storyblok/astro";
import { getLiveStory, useStoryblokApi, type ISbStoryData } from "@storyblok/astro";
import StoryblokComponent from "@storyblok/astro/StoryblokComponent.astro";

const { slug } = Astro.params;

const story = await useStoryblok(
// The slug to fetch
`cdn/stories/${slug === undefined ? "home" : slug}`,
// The API options
{
version: "draft",
},
// The Bridge options (optional, if an empty object, null, or false are set, the API options will be considered automatically as far as applicable)
{},
// The Astro object (essential for the live preview functionality)
Astro
);
let story: ISbStoryData = null;

const liveStory = await getLiveStory(Astro);

if (liveStory) {
story = liveStory;
} else {
const sbApi = useStoryblokApi();
const { data } = await sbApi.get(
`cdn/stories/${slug === undefined ? "home" : slug}`,
{
version: "draft",
resolve_relations: ["featured-articles.posts"],
}
);
story = data?.story;
}
---

<StoryblokComponent blok={story.content} />
```
2. You can also listen to when the live preview is updated.
```js
<script>
document.addEventListener("storyblok-live-preview-updated", () => {
// console.log("Live preview: body updated");
// initUnoCssRuntime(); regenerate all the css
});
</script>
```
## The Storyblok JavaScript SDK Ecosystem
![A visual representation of the Storyblok JavaScript SDK Ecosystem](https://a.storyblok.com/f/88751/2400x1350/be4a4a4180/sdk-ecosystem.png/m/1200x0)
Expand Down
74 changes: 24 additions & 50 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import type { AstroGlobal, AstroIntegration } from "astro";
import type {
ISbConfig,
ISbRichtext,
ISbStoriesParams,
ISbStoryData,
SbRichTextOptions,
StoryblokBridgeConfigV2,
StoryblokClient,
} from "./types";
import { vitePluginStoryblokBridge } from "./vite-plugins/vite-plugin-storyblok-bridge";
import { initStoryblokBridge } from "./utils/initStoryblokBridge";
export { handleStoryblokMessage } from "./live-preview/handleStoryblokMessage";

export {
Expand All @@ -33,25 +32,10 @@ export function useStoryblokApi(): StoryblokClient {
return globalThis.storyblokApiInstance;
}

export async function useStoryblok(
slug: string,
apiOptions: ISbStoriesParams = {},
bridgeOptions: StoryblokBridgeConfigV2 = {},
Astro: AstroGlobal
) {
if (!globalThis.storyblokApiInstance) {
console.error("storyblokApiInstance has not been initialized correctly");
}
export async function getLiveStory(Astro: AstroGlobal) {
let story: ISbStoryData = null;
if (Astro && Astro.locals["_storyblok_preview_data"]) {
story = Astro.locals["_storyblok_preview_data"];
} else {
const { data } = await globalThis.storyblokApiInstance.get(
slug,
apiOptions,
bridgeOptions
);
story = data.story;
}
return story;
}
Expand Down Expand Up @@ -120,17 +104,25 @@ export type IntegrationOptions = {
livePreview?: boolean;
};

export default function storyblokIntegration(
options: IntegrationOptions
): AstroIntegration {
export default function storyblokIntegration({
useCustomApi = false,
bridge = true,
componentsDir = "src",
enableFallbackComponent = false,
livePreview = false,
...restOptions
}: IntegrationOptions): AstroIntegration {
const resolvedOptions = {
useCustomApi: false,
bridge: true,
componentsDir: "src",
enableFallbackComponent: false,
livePreview: false,
...options,
useCustomApi,
bridge,
componentsDir,
enableFallbackComponent,
livePreview,
...restOptions,
};

const initBridge = initStoryblokBridge(bridge);

return {
name: "@storyblok/astro",
hooks: {
Expand All @@ -156,10 +148,6 @@ export default function storyblokIntegration(
resolvedOptions.customFallbackComponent
),
vitePluginStoryblokOptions(resolvedOptions),
vitePluginStoryblokBridge(
resolvedOptions.livePreview,
config.output
),
],
},
});
Expand All @@ -168,6 +156,7 @@ export default function storyblokIntegration(
"To utilize the Astro Storyblok Live feature, Astro must be configured to run in SSR mode. Please disable this feature or switch Astro to SSR mode."
);
}

injectScript(
"page-ssr",
`
Expand All @@ -178,26 +167,14 @@ export default function storyblokIntegration(

// This is only enabled if experimentalLivePreview is disabled and bridge is enabled.

if (resolvedOptions.bridge && !resolvedOptions.livePreview) {
let initBridge: string = "";

if (typeof resolvedOptions.bridge === "object") {
const bridgeConfigurationOptions = { ...resolvedOptions.bridge };
initBridge = `const storyblokInstance = new StoryblokBridge(${JSON.stringify(
bridgeConfigurationOptions
)});`;
} else {
initBridge = "const storyblokInstance = new StoryblokBridge()";
}

if (bridge && !livePreview) {
injectScript(
"page",
`
import { loadStoryblokBridge } from "@storyblok/astro";
loadStoryblokBridge().then(() => {
const { StoryblokBridge, location } = window;
${initBridge}
storyblokInstance.on(["published", "change"], (event) => {
if (!event.slugChanged) {
location.reload(true);
Expand All @@ -209,19 +186,16 @@ export default function storyblokIntegration(
}

// This is only enabled if experimentalLivePreview feature is on
if (resolvedOptions.livePreview) {
if (livePreview) {
injectScript(
"page",
`
import { loadStoryblokBridge, handleStoryblokMessage } from "@storyblok/astro";
import { bridgeOptions } from "virtual:storyblok-bridge";
console.info("The Storyblok Astro live preview feature is currently in an experimental phase, and its API is subject to change in the future.")
loadStoryblokBridge().then(() => {
const { StoryblokBridge, location } = window;
if(bridgeOptions){
const storyblokInstance = new StoryblokBridge(bridgeOptions);
storyblokInstance.on(["published", "change", "input"], handleStoryblokMessage);
};
${initBridge}
storyblokInstance.on(["published", "change", "input"], handleStoryblokMessage);
});
`
);
Expand Down
2 changes: 2 additions & 0 deletions lib/live-preview/handleStoryblokMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export async function handleStoryblokMessage(event: {
// Get current focused element in Storyblok
const focusedElem = document.querySelector('[data-blok-focused="true"]');
updateDOMWithNewBody(currentBody, newBody, focusedElem);
// Dispatch a custom event after the body update
document.dispatchEvent(new Event("storyblok-live-preview-updated"));
};
const debounceDelay = 500; // Adjust the delay as needed
clearTimeout(timeout);
Expand Down
33 changes: 0 additions & 33 deletions lib/utils/generateFinalBridgeObject.ts

This file was deleted.

11 changes: 11 additions & 0 deletions lib/utils/initStoryblokBridge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { StoryblokBridgeConfigV2 } from "../types";

export function initStoryblokBridge(
config: boolean | StoryblokBridgeConfigV2
): string {
if (typeof config === "object") {
const bridgeConfig = JSON.stringify(config);
return `const storyblokInstance = new StoryblokBridge(${bridgeConfig});`;
}
return "const storyblokInstance = new StoryblokBridge();";
}
66 changes: 0 additions & 66 deletions lib/utils/parseAstCode.ts

This file was deleted.

Loading

0 comments on commit 9d7a619

Please sign in to comment.