V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
ooo4
V2EX  ›  问与答

如何增量地将 markdown 转换成 html?

  •  
  •   ooo4 · 1 天前 · 473 次点击

    现在后台是流式输出 markdown 字符串,并且每次我也不断处理全量的 markdown 字符串,再使用MarkdownContent这个组件去渲染成 html

    但这样会导致一个问题,就是在流式输出的过程中,由于会不断地执行这个MarkdownView组件,导致无法使用鼠标选中渲染后的文本,等下次 render 时,选中状态就又丢失了

    有什么方案能够增量更新吗,不操作以前的 dom

    // 大概就这样的逻辑
    function App() {
      const [message, setMessage] = useState('')
      async function foo() {
        const reader = response.body?.getReader();
        const decoder = new TextDecoder();
        let result = "";
        while (true) {
          const { done, value } = await reader.read();
          if (done) break;
          result += decoder.decode(value);
          setMessage(result);
        }
      }
      return <MarkdownContent source={message}></MarkdownContent>;
    }
    
    
    export const MarkdownContent = memo(({ source }: MarkdownContentProps) => {
      const html = useMemo(() => markdown.render(source ?? ""), [source])
    
      return (
        <article
          className='prose dark:prose-invert'
          style={{ maxWidth: "100%" }}
          dangerouslySetInnerHTML={{ __html: html }}
        />
      )
    })
    
    第 1 条附言  ·  1 天前

    img 看了看chatgpt的dom结构,应该是对markdown内容进行了二次编译,才做到了增量更新的

    4 条回复    2025-02-28 09:32:17 +08:00
    jifengg
        1
    jifengg  
       1 天前
    实时想的,不知道可行性:
    根据 markdown 语法,对 markdown 进行最小切分。然后分别渲染后,append 到 dom 中。
    由于 markdown 大部分语法也都是流式的,只要你正确切分,就能分块渲染。
    当然也有一些不支持的,比如“文献引用”。但是影响不大。
    FakerLeung
        2
    FakerLeung  
       1 天前
    全量解析,再 diff ?
    sgiyy
        3
    sgiyy  
       1 天前
    1. 维护一个数组,每次返回的 markdown 数据按规则(比如换行)切分后推入数组
    2. 为了防止重复渲染,每个数组项维护一个唯一标识符( uid )。
    3. 每个数组项渲染一个类似 MarkdownItemContent 的组件
    my3157
        4
    my3157  
       14 小时 9 分钟前 via Android
    严谨一点的方法,做 tokenizer ,简单粗暴的方法,按行读取,用正则匹配需要成对出现的,比如 code block 这种,出现就就等结束符出现了再渲染
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2452 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 15:41 · PVG 23:41 · LAX 07:41 · JFK 10:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.