#include "ctai_cmark-gfm.h" namespace ctai_cmark_gfm { MarkdownStreamProcessor::MarkdownStreamProcessor(QTextEdit* textEdit) : m_textEdit(textEdit) , m_buffer() , m_tempText() { } MarkdownStreamProcessor::~MarkdownStreamProcessor() { // 确保在销毁时处理所有剩余的缓冲内容 if (!m_buffer.isEmpty()) { handleBufferOverflow(); } } void MarkdownStreamProcessor::appendMarkdown(const QString& text) { // 将新内容添加到缓冲区 QString newBuffer = m_buffer + text; // 检查是否超出缓冲区大小 if (newBuffer.size() > BUFFER_SIZE) { handleBufferOverflow(); newBuffer = text; } // 检查是否只包含开始标记 if (hasMarkdownStart(text) && !hasMarkdownEnd(text)) { m_buffer = newBuffer; m_tempText = text; m_textEdit->append(text); return; } // 检查是否包含结束标记 if (hasMarkdownEnd(text)) { QString fullContent = m_buffer + text; QString rendered = renderMarkdown(fullContent); replaceTempText(rendered); m_buffer.clear(); return; } m_buffer = newBuffer; } bool MarkdownStreamProcessor::hasMarkdownStart(const QString& text) { // 检查常见的Markdown开始标记 static const QStringList startMarkers = { "```", "~~~", "#", ">", "*", "_", "-", "+", "[", "|" }; for (const QString& marker : startMarkers) { if (text.contains(marker)) { return true; } } return false; } bool MarkdownStreamProcessor::hasMarkdownEnd(const QString& text) { // 检查常见的Markdown结束标记 static const QStringList endMarkers = { "```", "~~~", "\n\n", "]", "*", "_" }; for (const QString& marker : endMarkers) { if (text.contains(marker)) { return true; } } return false; } QString MarkdownStreamProcessor::renderMarkdown(const QString& text) { QByteArray textUtf8 = text.toUtf8(); char* rendered = cmark_markdown_to_html( textUtf8.constData(), textUtf8.size(), CMARK_OPT_DEFAULT ); QString result = QString::fromUtf8(rendered); free(rendered); return result; } void MarkdownStreamProcessor::handleBufferOverflow() { if (!m_buffer.isEmpty()) { QString rendered = renderMarkdown(m_buffer); replaceTempText(rendered); m_buffer.clear(); } } void MarkdownStreamProcessor::replaceTempText(const QString& newContent) { if (!m_tempText.isEmpty()) { // 获取当前文本 QString currentText = m_textEdit->toPlainText(); // 替换临时文本 currentText.replace(m_tempText, newContent); m_textEdit->setHtml(currentText); m_tempText.clear(); } else { m_textEdit->append(newContent); } } }