富文本解析

对html字符串进行解析展示,包括消毒和其他reactDom操作

先对html字符串进行消毒处理

import sanitizeHtml from 'sanitize-html';

// 自己配置消毒规则
const sanitizeHtmlOptiosn = {
  allowedTags: [
    "address", "article", "aside", "footer", "header", "h1", "h2", "h3", "h4",
    "h5", "h6", "hgroup", "main", "nav", "section", "blockquote", "dd", "div",
    "dl", "dt", "figcaption", "figure", "hr", "li", "main", "ol", "p", "pre",
    "ul", "a", "abbr", "b", "bdi", "bdo", "br", "cite", "code", "data", "dfn",
    "em", "i", "kbd", "mark", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp",
    "small", "span", "strong", "sub", "sup", "time", "u", "var", "wbr", "caption",
    "col", "colgroup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "font",
    "img", "video", "audio",
  ],
  disallowedTagsMode: 'discard',
  allowedAttributes: {
    font: [ 'color' ],
    a: [ 'href', 'name', 'target' ],
    img: [ 'src', 'srcset', 'alt', 'title', 'width', 'height', 'loading' ],
    video: ['preload', 'controls', 'src'],
    audio: ['src'],
    '*': ['style', 'class', 'id', 'data-kc'],
  },
  selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ],
  allowedSchemes: [ 'http', 'https', 'ftp', 'mailto', 'tel', 'message', 'copy', 'dingtalk', 'dtmd' ],
  allowedSchemesByTag: {},
  allowedSchemesAppliedToAttributes: [ 'href', 'src', 'cite' ],
  allowProtocolRelative: true,
  enforceHtmlBoundary: false
}

const str1 = sanitizeHtml(str, sanitizeHtmlOptiosn); //使用 sanitizeHtml 对html字符串消毒

对消毒的内容解析展示

import parse, { domToReact, HTMLReactParserOptions, Element } from 'html-react-parser';
import { PhotoProvider, PhotoView } from 'react-photo-view';
import 'react-photo-view/dist/react-photo-view.css';


// 使用 react-photo-view 可以对图片处理,点击放大等(自己按需处理)
const options: HTMLReactParserOptions = {
    replace: domNode => {
      if (domNode instanceof Element && domNode.attribs) {
        const { attribs, children, name } = domNode;
        if (name === 'a') {
          return (
            <a style={{ color: '#4d96f8' }} href={attribs.href} target='_blank'>
              {domToReact(children, plainOptions)}
            </a>
          )
        }
        if (name === 'img') {
          return (
            <PhotoProvider photoClosable={true} bannerVisible={false}>
              <PhotoView src={attribs.src}>
                <img src={attribs.src} style={{ width: '100%', height: 'auto', objectFit: 'contain' }} /> 
              </PhotoView>
            </PhotoProvider>
          )
        }
        if (name === 'mark') {
          return <mark style={{ padding: 0 }}>{domToReact(children, plainOptions)}</mark>;
        }
      }
    }
  };
  
  return parse(str1, options);

附上完整代码

import React from 'react';
import sanitizeHtml from 'sanitize-html';
import parse, { domToReact, HTMLReactParserOptions, Element } from 'html-react-parser';
import { PhotoProvider, PhotoView } from 'react-photo-view';
import 'react-photo-view/dist/react-photo-view.css';

const sanitizeHtmlOptiosn = {
  allowedTags: [
    "address", "article", "aside", "footer", "header", "h1", "h2", "h3", "h4",
    "h5", "h6", "hgroup", "main", "nav", "section", "blockquote", "dd", "div",
    "dl", "dt", "figcaption", "figure", "hr", "li", "main", "ol", "p", "pre",
    "ul", "a", "abbr", "b", "bdi", "bdo", "br", "cite", "code", "data", "dfn",
    "em", "i", "kbd", "mark", "q", "rb", "rp", "rt", "rtc", "ruby", "s", "samp",
    "small", "span", "strong", "sub", "sup", "time", "u", "var", "wbr", "caption",
    "col", "colgroup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "font",
    "img", "video", "audio",
  ],
  disallowedTagsMode: 'discard',
  allowedAttributes: {
    font: [ 'color' ],
    a: [ 'href', 'name', 'target' ],
    img: [ 'src', 'srcset', 'alt', 'title', 'width', 'height', 'loading' ],
    video: ['preload', 'controls', 'src'],
    audio: ['src'],
    '*': ['style', 'class', 'id', 'data-kc'],
  },
  selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ],
  allowedSchemes: [ 'http', 'https', 'ftp', 'mailto', 'tel', 'message', 'copy', 'dingtalk', 'dtmd' ],
  allowedSchemesByTag: {},
  allowedSchemesAppliedToAttributes: [ 'href', 'src', 'cite' ],
  allowProtocolRelative: true,
  enforceHtmlBoundary: false
}

export function parseRichText(text: string) {
  const options: HTMLReactParserOptions = {
    replace: domNode => {
      if (domNode instanceof Element && domNode.attribs) {
        const { attribs, children, name } = domNode;
        if (name === 'a') {
          return (
            <a style={{ color: '#4d96f8' }} href={attribs.href} target="_blank">
              {domToReact(children, detailOptions)}
            </a>
          )
        }
        if (name === 'img') {
          return (
            <PhotoProvider photoClosable={true} bannerVisible={false}>
              <PhotoView src={attribs.src}>
                <img src={attribs.src} style={{ width: '100%', height: 'auto', objectFit: 'contain' }} /> 
              </PhotoView>
            </PhotoProvider>
          )
        }
        if (name === 'mark') {
          return <mark style={{ padding: 0 }}>{domToReact(children, detailOptions)}</mark>;
        }
      }
    }
  };
  
  return parse(sanitizeHtml(text, sanitizeHtmlOptiosn), options);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

叨槿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值