Skip to content

Commit

Permalink
feat: added @storyblok/richtext and types
Browse files Browse the repository at this point in the history
  • Loading branch information
alvarosabu committed Jul 5, 2024
1 parent c1627b3 commit c478211
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 30 deletions.
15 changes: 15 additions & 0 deletions lib/components/SbRichText.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script setup lang="ts">
import { useSbRichtext } from "../composables/useRichText";
const props = defineProps<{ doc: any; resolvers?: any }>();
const { render } = useSbRichtext({
resolvers: props.resolvers,
});
const root = () => render(props.doc);
</script>

<template>
<root />
</template>
48 changes: 48 additions & 0 deletions lib/composables/useRichText.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { VNode } from "vue";
import { createTextVNode, h } from "vue";
/* import { RouterLink } from 'vue-router'
*/
import type {
Node,
NodeResolver,
SbRichtextOptions,
} from "@storyblok/richtext";
import {
BlockTypes,
/* MarkTypes, */ richTextResolver,
} from "@storyblok/richtext";
import { StoryblokComponent } from "@storyblok/vue";

const componentResolver: NodeResolver<VNode> = (node: Node<VNode>): VNode => {
return h(
StoryblokComponent,
{
blok: node?.attrs?.body[0],
id: node.attrs?.id,
},
node.children
);
};

export function useSbRichtext(options: SbRichtextOptions<VNode>) {
const mergedOptions: SbRichtextOptions<VNode> = {
renderFn: h,
textFn: createTextVNode,
resolvers: {
/* [MarkTypes.LINK]: (node: Node<VNode>) => {
return node.attrs?.linktype === 'STORY'
? h(RouterLink, {
to: node.attrs?.href,
target: node.attrs?.target,
}, node.text)
: h('a', {
href: node.attrs?.href,
target: node.attrs?.target,
}, node.text)
}, */
[BlockTypes.COMPONENT]: componentResolver,
...options.resolvers,
},
};
return richTextResolver<VNode>(mergedOptions);
}
41 changes: 17 additions & 24 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,27 @@ import {

import type {
StoryblokClient,
SbSDKOptions,
StoryblokBridgeConfigV2,
ISbStoryData,
ISbStoriesParams,
SbVueSDKOptions,
} from "./types";

export {
useStoryblokBridge,
apiPlugin,
renderRichText,
RichTextSchema,
RichTextResolver,
} from "@storyblok/js";

import StoryblokComponent from "./StoryblokComponent.vue";
export { default as StoryblokComponent } from "./StoryblokComponent.vue";
import SbRichText from "./components/SbRichText.vue";
export { default as SbRichText } from "./components/SbRichText.vue";

export * from "./composables/useRichText";

const vEditableDirective: Directive<HTMLElement> = {
beforeMount(el, binding) {
if (binding.value) {
Expand All @@ -39,17 +54,6 @@ export const useStoryblokApi = (): StoryblokClient => {
return storyblokApiInstance;
};

export {
useStoryblokBridge,
apiPlugin,
renderRichText,
RichTextSchema,
RichTextResolver,
} from "@storyblok/js";

import StoryblokComponent from "./StoryblokComponent.vue";
export { default as StoryblokComponent } from "./StoryblokComponent.vue";

export const useStoryblok = async (
url: string,
apiOptions: ISbStoriesParams = {},
Expand Down Expand Up @@ -84,23 +88,12 @@ export const useStoryblok = async (
return story;
};

export interface SbVueSDKOptions extends SbSDKOptions {
/**
* Show a fallback component in your frontend if a component is not registered properly.
*/
enableFallbackComponent?: boolean;
/**
* Provide a custom fallback component, e.g. "CustomFallback".
*/
customFallbackComponent?: string;
}

// Plugin
export const StoryblokVue: Plugin = {
install(app, pluginOptions: SbVueSDKOptions = {}) {
app.directive("editable", vEditableDirective);
app.component("StoryblokComponent", StoryblokComponent);

app.component("SbRichText", SbRichText);
if (
pluginOptions.enableFallbackComponent &&
!pluginOptions.customFallbackComponent
Expand Down
3 changes: 2 additions & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
"prepublishOnly": "npm run build && cp ../README.md ./"
},
"dependencies": {
"@storyblok/js": "^3.0.8"
"@storyblok/js": "^3.0.8",
"@storyblok/richtext": "^0.2.0"
},
"devDependencies": {
"@babel/core": "^7.24.7",
Expand Down
12 changes: 11 additions & 1 deletion lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { SbSDKOptions } from "@storyblok/js";
import type StoryblokComponent from "./StoryblokComponent.vue";

declare module "@vue/runtime-core" {
Expand Down Expand Up @@ -36,4 +37,13 @@ export type {
StoryblokClient,
} from "@storyblok/js";

export type { SbVueSDKOptions } from "./index";
export interface SbVueSDKOptions extends SbSDKOptions {
/**
* Show a fallback component in your frontend if a component is not registered properly.
*/
enableFallbackComponent?: boolean;
/**
* Provide a custom fallback component, e.g. "CustomFallback".
*/
customFallbackComponent?: string;
}
33 changes: 32 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion playground/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
import Home from "./pages/HomeShort.vue";
import Home from "./pages/Home.vue";
</script>

<template>
Expand Down
2 changes: 1 addition & 1 deletion playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@storyblok/vue-playground",
"version": "0.0.0",
"scripts": {
"demo": "vite",
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
Expand Down
59 changes: 58 additions & 1 deletion playground/pages/Home.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script setup>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { useStoryblokBridge, useStoryblokApi } from "@storyblok/vue";
Expand All @@ -15,8 +15,65 @@ story.value = data.story;
onMounted(() => {
useStoryblokBridge(story.value.id, (evStory) => (story.value = evStory));
});
const doc = {
type: "doc",
content: [
{
type: "bullet_list",
content: [
{
type: "list_item",
content: [
{
type: "paragraph",
content: [
{
text: "Bull",
type: "text",
marks: [{ type: "italic" }],
},
{
text: "et 1",
type: "text",
marks: [{ type: "bold" }],
},
],
},
],
},
{
type: "list_item",
content: [
{
type: "paragraph",
content: [{ text: "Bullet 2", type: "text" }],
},
],
},
{
type: "list_item",
content: [
{
type: "paragraph",
content: [
{
text: "Bullet 3",
type: "text",
marks: [{ type: "styled", attrs: { class: "css-class" } }],
},
],
},
],
},
{ type: "list_item", content: [{ type: "paragraph" }] },
],
},
],
};
</script>

<template>
<SbRichText :doc="doc" />
<StoryblokComponent v-if="story" :blok="story.content" />
</template>

0 comments on commit c478211

Please sign in to comment.