npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

kontent-rich-text-for-vue

v2.0.0

Published

A component for rendering Kentico Kontent rich text elements in vue.js

Downloads

560

Readme

Render rich text from Kentico Kontent in Vue

This package replaces the resolveHtml method provided by the Kontent Delivery SDK to display value of rich text elements.

Kentico Kontent allows you to write content in rich text elements, where you can do all sorts of formatting. What's more interesting, you can also compose your content from inline or reusable bits of content, referred to as components and linked items respectively.

When you don't need this package

  • You're not using these, you can stop reading and go on with your life.
  • You're using components or linked items and happy with the way the Kontent Delivery SDK handles rendering linked items.
  • You're not using Kentico Kontent with Vue.
  • You're not using Kentico Kontent at all.

When you want components to be components, though...

The richTextResolver extension point of the SDK does decent job, but I wanted my components to be proper components in the framework I was using. That happened to be Vue.js at the moment. So I wrote this tiny component that makes some of my dreams come true.

Installation

Pick the package up form npm:

npm install kontent-rich-text-for-vue --save

Basic usage

This package contains a component that accepts the raw rich text value from Kentico Kontent delivery API and your component that will replace each linked item or component found in the text.

Let's say we have content in items of content type blog_post where there are 2 elements:

  • title is a regular text that can be rendered as-is
  • content is a rich text and needs a bit more love
<template>
  <h1>{{blogPost.title.value}}</h1>
  <div> <!-- here you would normally put attribute v-html='blogPost.content.resolveHtml()' but no more -->
    <rich-text
      :content='blogPost.content.value'
      :linkedItemComponent='linkedItemComponent'
    />
  </div>
</template>

<script>
  import { RichText } from 'kontent-rich-text-for-vue';
  import LinkedItem from './components/linked-item.vue';

  export default {
    components: { RichText },
    computed: {
      blogPost: () => blogPost, // Pick it up from a vuex store or wherever you happen to keep it
      linkedItemComponent: () => LinkedItem
    }
  }
</script>

Now, my linked-item component will need to decide how various linked items and components appearing in the text should look like.

To make pairing of linked item components with linked item data easier, one more thing is exported from this package.

<script>
  import { linkedItemFactory } from 'kontent-rich-text-for-vue';
  import YoutubeVideo from './youtube-video.vue';
  import Quote from './quote.vue';
  
  const selectComponent = (contentTypeCodeName) => {
    switch (contentTypeCodeName) {
      case 'youtube_video':
        return YoutubeVideo;
      case 'quote':
        return Quote;
    }
  };

  export default {
    functional: true,
    render: (createElement, context) => {
      const {props} = context;

      const selectLinkedItemData = (itemCodeName) => {
        // Again, pick the blogPost from a vuex store or wherever.
        // I ended up having page 'provide' the blogPost  and then injected it here.
        return blogPost.linkedItems[itemCodeName]; 
      };      

      const component = linkedItemFactory(selectComponent, selectLinkedItemData);
      return createElement(component, {props})
    }
  }
</script>

With this rather complicated setup out of the way, we can start writing components for individual linked item types. The rich-text component passes to the linked items one prop and that is the item containing all the linked item data. In the case of our YouTube video, it contains a video ID and a short description.

<template>
  <figure>
    <iframe
      :src='`https://youtube.com/embed/${item.videoId.value}?rel=0`'
    >    
    </iframe>
    <figcaption>{{item.description.value}}</figcaption>
  </figure>
</template>

<script>
  export default {
    props: ['item']
  }
</script>

Links

Kontent allows you to add various types of links in your rich text. Out of these types, the content item link needs its URL resolved to render properly. The link itself contains only ID of the linked content item. Usually more data, such as codename, content type, or url slug of the particular content item is needed for construction of the URL. These values can be obtained from the links field in the rich text element value.

To make this resolution a bit easier, another factory is exported from this package. However, the factory needs to be injected with the url construction logic, and possibly with customized component to be rendered instead of the plain a element.

<template>
  <h1>{{blogPost.title.value}}</h1>
  <div>
    <rich-text
      :content='blogPost.content.value'
      :linkComponent='linkComponent'
    />
  </div>
</template>

<script>
  import { RichText, linkFactory } from 'kontent-rich-text-for-vue';
  import CustomEmailLink from './components/custom-email-link.vue';

  export default {
    components: { RichText },
    computed: {
      blogPost: () => blogPost, // Pick it up from a vuex store or wherever you happen to keep it
      linkComponent: () => linkFactory({
        getLinkComponent: linkType => {
          // Can be 'content-item' | 'asset' | 'email' | 'web-url'
          if (linkType === 'email') {
            return CustomEmailLink;
          }          
          // Otherwise use the default component.
          return null;
        },
        getItemLinkUrl: itemId => {
          const {codename, urlSlug, type} = blogPost.content.links.find(link => link.linkId === itemId);
          return `https://www.myblog.com/posts/${urlSlug}`;
        }
      })
    }
  }
</script>

The linkComponent is an optional prop and is not necessary unless you need content item link's URLs resolved or link rendering customized in any other way.

Rich text in a rich text

Another content type used as a component or linked item in our example also contains a rich text element quote. We'll wrap the value in the same rich-text component we used on the parent page. And in case this text contains nested linked items, we'll also pass the linked-item component.

<template>
  <blockquote>
    <rich-text
      :content='item.quote.value'
      :linkedItemComponent='linkedItemComponent'
    />
  </blockquote>
</template>

<script>
  import { RichText } from 'kontent-rich-text-for-vue';
  import LinkedItem from './linked-item.vue';

  export default {
    props: ['item'],
    components: {RichText},
    computed: {
      linkedItemComponent: () => LinkedItem
    }
  }
</script>

These example components are extremely small and could be easily handled by the out-of-the-box richTextResolver, but as the components grew to render more and more of markup, messing with string interpolation became rather obnoxious.

Feedback & Contributions

The provided component is quite bare-bones, but does everything I need. I'm interested if your use case differs and thus my implementation lacks.

Furthermore, I'm no Vue expert, so I'd love to hear if there are nicer or more elegant ways of doing things.