仿照chatgpt代码块高亮

我们公司最近写了一个仿照gpt回答用户问题的网站
我要实现一个功能,正确展示代码,如下图:
仿照chatgpt代码块高亮_第1张图片
这里面我遇到了一些问题,记录下来:

1、代码高亮

后端返回的markdown格式的字符串,所以我要用插件转化为dom结构,这里我使用的插件是:markdown-it,代码高亮我使用的插件是:highlight.js

markdonw-it官方文档:https://markdown-it.docschina.org/

我按照官方文档写了如下代码:

<span v-html="mdToHtml(content)">span>
import hljs from "highlight.js";
import 'highlight.js/styles/a11y-dark.css'
// 通常的默认值们
var md = require('markdown-it')('commonmark', {
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return '
' +
               hljs.highlight(lang, str, true).value +
               '
'
; } catch (__) {} } return '
' + md.utils.escapeHtml(str) + '
'
; } }); export default { methods: { mdToHtml(content) { return md.render(content) }, }

2、系统回答问题的过程中字体忽大忽小

QQ录屏20231106180307

从视频里明显的看到材料两个字由大变小,体验不好

这个有问题的回答,后端返给我的字符串是这个:

content: "鱼香肉丝是一道经典的川菜,下面是鱼香肉丝的做法步骤:\n\n材料:\n- 猪肉(瘦肉):150克......"

把内容固定为:

<span v-html="mdToHtml(`\n\n材料:\n-`)">span>

现在展示的样式是:
仿照chatgpt代码块高亮_第2张图片

把内容固定为:

<span v-html="mdToHtml(`\n\n材料:\n- 猪肉(瘦肉)`)">span>

现在展示的样式是:
仿照chatgpt代码块高亮_第3张图片

问题这就找到了,那我想如果markdown-it遇到其他的字符串不去解析成dom,只在遇到代码字符串的时候解析成dom,这个问题就解决了

markdown-it git地址:markdown-it

在项目里找到这个文件:lib/presets/commonmark.js,把components对象复制过来,然后我试了试,只留下fence和paragraph的时候可以达到我想要的效果

md.configure({
    components: {
        core: {
            rules: [
                'normalize',
                'block',
                'inline',
                'text_join'
            ]
        },

        block: {
            rules: [
                // 'blockquote',
                // 'code',
                'fence',
                // 'heading',
                // 'hr',
                // 'html_block',
                // 'lheading',
                // 'list',
                // 'reference',
                'paragraph'
            ]
        },

        inline: {
            rules: [
                // 'autolink',
                // 'backticks',
                // 'emphasis',
                // 'entity',
                // 'escape',
                // 'html_inline',
                // 'image',
                // 'link',
                // 'newline',
                // 'text'
            ],
            rules2: [
                // 'balance_pairs',
                // 'emphasis',
                // 'fragments_join'
            ]
        }
    }
});

这个问题就这样解决了

你可能感兴趣的:(javascript,vue.js)