Skip to content

Feature Request: Source code highlight and math formula rendering #10758

Closed
@xintq

Description

@xintq

Prerequisites

  • I am running the latest code. Mention the version if possible as well.
  • I carefully followed the README.md.
  • I searched using keywords relevant to my issue to make sure that I am creating a new issue that is not already open (or closed).
  • I reviewed the Discussions, and have a new and useful enhancement to share.

Feature Description

  1. Highlight the source code in messages.
  2. Render the mathematical formulas in messages.
    image

Motivation

The following are missing in the default webui:

  1. Highlight the source code in messages.
  2. Render the mathematical formulas in messages.

Possible Implementation

This can be down by using highlight.js and markdown-it-katex-gpt in the llama-server webui.
I've implemented this by the following steps.

  1. Install the packages in webui
npm install highlight.js
npm install markdown-it-katex-gpt
  1. Modify main.js like
// Add these two line at the beginning
import 'highlight.js/styles/github-dark-dimmed.min.css'
import 'katex/dist/katex.min.css'
import hljs from 'highlight.js' // https://highlightjs.org
import markdownItKatexGpt from 'markdown-it-katex-gpt'
...
// markdown support
const VueMarkdown = defineComponent(
  (props) => {
    const md = shallowRef(new MarkdownIt({
      breaks: true,
      highlight: function (str, lang) { // Add highlight.js
        if (lang && hljs.getLanguage(lang)) {
          try {
            return '<pre><code class="hljs">' +
                   hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
                   '</code></pre>';
          } catch (__) {}
        }
        return '<pre><code class="hljs">' + md.value.utils.escapeHtml(str) + '</code></pre>';
      }
    }));
    md.value.use(markdownItKatexGpt, { // Add katex support
      delimiters: [
        { left: '\\[', right: '\\]', display: true },
        { left: '\\(', right: '\\)', display: false },
        { left: '$$', right: '$$', display: false },
      ]
    })

    const origFenchRenderer = md.value.renderer.rules.fence;
    md.value.renderer.rules.fence = (tokens, idx, ...args) => {
      const content = tokens[idx].content;
      const origRendered = origFenchRenderer(tokens, idx, ...args);
      return `<div class="relative my-4">
        <div class="text-right sticky top-4 mb-2 mr-2 h-0">
          <button class="badge btn-mini" onclick="copyStr(${escapeAttr(JSON.stringify(content))})">📋 Copy</button>
        </div>
        ${origRendered}
      </div>`;
    };
    window.copyStr = copyStr;
    const content = computed(() => md.value.render(props.source));
    return () => h("div", { innerHTML: content.value });
  },
  { props: ["source"] }
);

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions