如何在 Nuxt 3 中将 editor-js Strapi 中的 json 富文本渲染为 html?

问题描述 投票:0回答:2

这是我在 Strapi 上创建的富文本编辑器的输出。

"{"时间":1679496880268,"块":[{"id":"82C13q17QU","类型":"段落","数据":{"文本":"标题"}},{" id":"aQ7sSPshJO","type":"段落","data":{"text":"描述"}},{"id":"P0cESzO_a-","type":"image","data ":{"文件":{"url":"/uploads/render_3fc01e6769.png","mime":"image/png","高度":1000,"宽度":1000,"尺寸":672.3," alt":"render.png","格式":{"thumbnail":{"name":"thumbnail_render.png","hash":"thumbnail_render_3fc01e6769","ext":".png","mime": "image/png","path":null,"width":156,"height":156,"size":49.79,"url":"/uploads/thumbnail_render_3fc01e6769.png"},"small":{"名称":"small_render.png","哈希":"small_render_3fc01e6769","ext":".png","mime":"image/png","路径":null,"宽度":500,"高度":500,"大小":529.93,"url":"/uploads/small_render_3fc01e6769.png"},"medium":{"name":"medium_render.png","hash":"medium_render_3fc01e6769","ext" :“.png”,“mime”:“image/png”,“路径”:null,“宽度”:750,“高度”:750,“大小”:1200.69,“url”:“/uploads/medium_render_3fc01e6769。 png"}}},"caption":"一杯咖啡","withBorder":false,"拉伸":false,"withBackground":false}}],"version":"2.23.2"}"

我想在Nuxt 3中显示为html。希望有人可以帮助我! 谢谢!

strapi nuxtjs3 rich-text-editor editorjs nuxt-strapi
2个回答
0
投票

我通过在 Nuxt3 TS 项目中创建

RichTextBlocks.vue
组件解决了这个问题。它使用Tailwind 的排版插件。这是我的组件:

<script lang="ts" setup>
import type { RichTextBlockChild, RichTextBlocks } from '@/ts/interfaces/strapi-models/strapiRichText'
import { RichTextBlockChildType, RichTextBlockFormat, RichTextBlockType } from '@/ts/interfaces/strapi-models/strapiRichText'

defineProps<{
  data?: RichTextBlocks[]
}>()

function renderList(block: RichTextBlocks) {
  let html = ''
  block.children.forEach((child) => {
    html += '<li>'
    child.children.forEach((childChild) => {
      if (childChild.type === RichTextBlockChildType.text) {
        if (childChild.bold)
          html += `<strong>${childChild.text}</strong>`
        else if (childChild.italic)
          html += `<i>${childChild.text}</i>`
        else if (childChild.underline)
          html += `<u>${childChild.text}</u>`
        else if (childChild.strikethrough)
          html += `<s>${childChild.text}</s>`
        else
          html += childChild.text
      }
    })
    html += '</li>'
  })

  return html
}

function renderText(children: RichTextBlockChild[]) {
  let html = ''
  children.forEach((childChild) => {
    if (childChild.type === RichTextBlockChildType.text) {
      if (childChild.bold)
        html += `<strong>${childChild.text}</strong>`
      else if (childChild.italic)
        html += `<i>${childChild.text}</i>`
      else if (childChild.underline)
        html += `<u>${childChild.text}</u>`
      else if (childChild.strikethrough)
        html += `<s>${childChild.text}</s>`
      else
        html += childChild.text
    }
  })

  return html
}
</script>

<template>
  <div class="prose prose-slate prose-a:text-blue-600">
    <template v-for="(block, index) in data" :key="index">
      <!-- Paragraph -->
      <p v-if="block && block.type === RichTextBlockType.paragraph">
        <template v-for="(child, childIndex) in block.children" :key="`${childIndex}-${index}`">
          <strong v-if="child.type === RichTextBlockChildType.text && child.bold">{{ child.text }}</strong>
          <i v-else-if="child.type === RichTextBlockChildType.text && child.italic">{{ child.text }}</i>
          <u v-else-if="child.type === RichTextBlockChildType.text && child.underline">{{ child.text }}</u>
          <s v-else-if="child.type === RichTextBlockChildType.text && child.strikethrough">{{ child.text }}</s>
          <code v-else-if="child.type === RichTextBlockChildType.text && child.code">{{ child.text }}</code>
          <a v-else-if="child.type === RichTextBlockChildType.link && child.url" :href="child.url" v-html="renderText(child.children)" />
          <template v-else-if="child.type === RichTextBlockChildType.text">
            {{ child.text }}
          </template>
        </template>
      </p>

      <!-- Lists -->
      <ul v-if="block && block.type === RichTextBlockType.list && block.format === RichTextBlockFormat.unordered" v-html="renderList(block)" />
      <ol v-if="block && block.type === RichTextBlockType.list && block.format === RichTextBlockFormat.ordered" v-html="renderList(block)" />

      <!-- Headings -->
      <h1 v-if="block && block.type === RichTextBlockType.heading && block.level === 1" v-html="renderText(block.children)" />
      <h2 v-if="block && block.type === RichTextBlockType.heading && block.level === 2" v-html="renderText(block.children)" />
      <h3 v-if="block && block.type === RichTextBlockType.heading && block.level === 3" v-html="renderText(block.children)" />
      <h4 v-if="block && block.type === RichTextBlockType.heading && block.level === 4" v-html="renderText(block.children)" />
      <h5 v-if="block && block.type === RichTextBlockType.heading && block.level === 5" v-html="renderText(block.children)" />
      <h6 v-if="block && block.type === RichTextBlockType.heading && block.level === 6" v-html="renderText(block.children)" />

      <!-- Image -->
      <nuxt-img
        v-if="block && block.type === RichTextBlockType.image && block.image"
        provider="imagekit"
        :src="getPathForImage(block.image)"
        width="1000"
        :placeholder="15"
        :modifiers="{ f: 'webp' }"
        lazy="true"
        :alt="block.image.alternativeText ?? ''"
        :title="block.image.name"
        class=""
      />
    </template>
  </div>
</template>

它支持 TS,这是我的

strapiRichText.ts
文件,其中包含接口:

import type StrapiImage from "./image";

export enum RichTextBlockType {
  paragraph = 'paragraph',
  list = 'list',
  heading = 'heading',
  image = 'image',
}

export enum RichTextBlockFormat {
  unordered = 'unordered',
  ordered = 'ordered',
}

export enum RichTextBlockChildType {
  text = 'text',
  list_item = 'list-item',
  link = 'link',
}

export interface RichTextBlocks {
  type: RichTextBlockType;
  children: RichTextBlockChild[];
  format?: RichTextBlockFormat
  level?: number
  image?: StrapiImage
}

export interface RichTextBlockChild {
  text: string
  url: string
  type: RichTextBlockChildType
  children: RichTextBlockChild[]
  bold?: boolean;
  underline?: boolean;
  italic?: boolean;
  strikethrough?: boolean;
  code?: boolean;
}

在我的其他组件或页面中,我可以像这样使用我的组件:

<RichTextBlocks v-if="props.data?.text" :data="props.data?.text" class="mb-10" />

我希望这对将来的任何人都有帮助!


-1
投票

应该有一种方法可以将富文本查询为markdown,参见:https://strapi.io/blog/build-a-blog-with-next-react-js-strapi

然后您应该能够使用

vue-markdown
将富文本内容呈现为格式化 HTML:

<vue-markdown>{{ markdownResponse }}</vue-markdown>
© www.soinside.com 2019 - 2024. All rights reserved.