Tags

external
Vue.js
Rich text

Svelte rich text renderer

For Svelte, there is a helper library that makes the integration process of rich texts very simple.

To install, use npm or another package manager:

npm install @caisy/rich-text-svelte-renderer --save

For ease of use, just pass the JSON and the component will convert it to HTML:

<script lang="ts">
import { RichTextRenderer } from '@caisy/rich-text-svelte-renderer';
...
</script>
{#if data.text && data.text.json}
	<RichTextRenderer node={data.text.json} />
{/if}

to ensure that you pass the correct object, it should contain something like this:

{ type: "doc", ... }

An example using the rich text render with Svelte can also be found here on Stackblitz:
https://stackblitz.com/github/caisy-io/caisy-example-sveltekit

Document Linking

More advanced use case is for example to support linked assets or documents.
Therefor you need to fetch the connections and the json from the graphql API.
So the RichTextRenderer with its child components might look like this:

src/components/fulltext/Fulltext.svelte
<script lang="ts">
	import { RichTextRenderer } from '@caisy/rich-text-svelte-renderer';
	import DocumentLink from './overwrites/DocumentLink.svelte';

	export let text: {
		connections?: any[];
		json?: any;
	};
</script>

{#if text}
	<RichTextRenderer
		overwrites={{ documentLink: DocumentLink }}
		connections={text?.connections}
		node={text?.json}
	/>
{/if}

Where your DocumentLink and Asset component would look like this, to render a linked Asset:

src/components/fulltext/overwrites/DocumentLink.svelte
<script lang="ts">
	import Asset from '../../Asset.svelte';
	export let node: any;
	export let connections: any | undefined;
</script>

{#each connections as component}
	{#if component?.__typename == 'Asset' && node?.attrs?.documentId == component.id}
		<Asset src={component.src} description={component.description} />
	{/if}
{/each}
<slot />
src/components/Asset.svelte
<script lang="ts">
	export let src: string;
	export let description: string;
</script>

{#if src}
	<img
		loading="lazy"
		src={`${src}?w=1920&h=960`}
		srcset={`${src}?w=3840&h=1920 1920w, ${src}?w=1920&h=960 1280w, ${src}?w=1280&h=640 640w`}
		alt={description ?? ''}
	/>
{/if}

This should just give an idea, how to use the rich-text library we provide. You could replace the img component with the image component from Next.js. If you want to learn more about how to render images in the web, here is good place to look:

Here is a Stackblitz Example of this above in action:
https://stackblitz.com/edit/github-xtn4u8
Github: https://github.com/MoritzGruber/svelte-example-with-images-in-rich-text-from-caisy

Tags

external
Vue.js
Rich text