diff --git a/lib/components/SbRichText.vue b/lib/components/SbRichText.vue new file mode 100644 index 00000000..ecf6cde9 --- /dev/null +++ b/lib/components/SbRichText.vue @@ -0,0 +1,15 @@ + + + diff --git a/lib/composables/useRichText.ts b/lib/composables/useRichText.ts new file mode 100644 index 00000000..3ae3ace5 --- /dev/null +++ b/lib/composables/useRichText.ts @@ -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 = (node: Node): VNode => { + return h( + StoryblokComponent, + { + blok: node?.attrs?.body[0], + id: node.attrs?.id, + }, + node.children + ); +}; + +export function useSbRichtext(options: SbRichtextOptions) { + const mergedOptions: SbRichtextOptions = { + renderFn: h, + textFn: createTextVNode, + resolvers: { + /* [MarkTypes.LINK]: (node: Node) => { + 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(mergedOptions); +} diff --git a/lib/index.ts b/lib/index.ts index 376dfa78..b03c8f6d 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -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 = { beforeMount(el, binding) { if (binding.value) { @@ -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 = {}, @@ -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 diff --git a/lib/package.json b/lib/package.json index 5b8add16..aad45989 100644 --- a/lib/package.json +++ b/lib/package.json @@ -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", diff --git a/lib/types.ts b/lib/types.ts index 5c048e1c..0a498c63 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -1,3 +1,4 @@ +import type { SbSDKOptions } from "@storyblok/js"; import type StoryblokComponent from "./StoryblokComponent.vue"; declare module "@vue/runtime-core" { @@ -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; +} diff --git a/package-lock.json b/package-lock.json index 7881c022..b6eaa1f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28,7 +28,8 @@ "name": "@storyblok/vue", "version": "0.0.1", "dependencies": { - "@storyblok/js": "^3.0.8" + "@storyblok/js": "^3.0.8", + "@storyblok/richtext": "^0.2.0" }, "devDependencies": { "@babel/core": "^7.24.7", @@ -4217,6 +4218,14 @@ "storyblok-js-client": "^6.7.2" } }, + "node_modules/@storyblok/richtext": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@storyblok/richtext/-/richtext-0.2.0.tgz", + "integrity": "sha512-mP3pwjWKmIttuiariKOg78jfz6kMeDGUEpfcvMleHk+aZ30xvvLmH4M2cXDoNVPMNxY+gfCT6xOk5n5jOjoj+g==", + "dependencies": { + "consola": "^3.2.3" + } + }, "node_modules/@storyblok/vue": { "resolved": "lib", "link": true @@ -6062,6 +6071,14 @@ "proto-list": "~1.2.1" } }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/conventional-changelog-angular": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", @@ -14538,6 +14555,14 @@ "storyblok-js-client": "^6.7.2" } }, + "@storyblok/richtext": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@storyblok/richtext/-/richtext-0.2.0.tgz", + "integrity": "sha512-mP3pwjWKmIttuiariKOg78jfz6kMeDGUEpfcvMleHk+aZ30xvvLmH4M2cXDoNVPMNxY+gfCT6xOk5n5jOjoj+g==", + "requires": { + "consola": "^3.2.3" + } + }, "@storyblok/vue": { "version": "file:lib", "requires": { @@ -14545,6 +14570,7 @@ "@cypress/vite-dev-server": "^5.1.0", "@cypress/vue": "^6.0.0", "@storyblok/js": "^3.0.8", + "@storyblok/richtext": "^0.2.0", "@vitejs/plugin-vue": "^5.0.5", "@vue/babel-preset-app": "^5.0.8", "@vue/test-utils": "2.4.6", @@ -16040,6 +16066,11 @@ "proto-list": "~1.2.1" } }, + "consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==" + }, "conventional-changelog-angular": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", diff --git a/playground/App.vue b/playground/App.vue index fd12d925..62cd7648 100644 --- a/playground/App.vue +++ b/playground/App.vue @@ -1,5 +1,5 @@