SPB Git forge

spb/immbot-ai

Public
1commits 1branches 0releases
1.5 MBsize
maindefault branch
20 days agolast push
TypeScript 98.3% CSS 0.9% Shell 0.7%
1.8 KB · 61 lines tsx
Raw Blame History
1"use client";2// Rendu Markdown des réponses : GFM + LaTeX (KaTeX), sans HTML brut (XSS),3// citations [Sx] transformées en puces cliquables.4import { memo } from "react";5import ReactMarkdown from "react-markdown";6import remarkGfm from "remark-gfm";7import remarkMath from "remark-math";8import rehypeKatex from "rehype-katex";910function prepareCitations(content: string): string {11  // [S3] → lien markdown interne que le composant « a » rend comme puce.12  return content.replace(/\[S(\d+)\]/g, "[S$1](#citation-$1)");13}1415export const Markdown = memo(function Markdown({16  content,17  onCitationClick,18  streaming,19}: {20  content: string;21  onCitationClick?: (index: number) => void;22  streaming?: boolean;23}) {24  return (25    <div className={`prose-immbot ${streaming ? "stream-cursor" : ""}`}>26      <ReactMarkdown27        remarkPlugins={[remarkGfm, remarkMath]}28        rehypePlugins={[rehypeKatex]}29        skipHtml30        components={{31          a({ href, children, ...props }) {32            if (href?.startsWith("#citation-")) {33              const index = parseInt(href.slice("#citation-".length), 10);34              return (35                <button36                  type="button"37                  className="citation-chip"38                  title={`Voir la source S${index}`}39                  onClick={(e) => {40                    e.preventDefault();41                    onCitationClick?.(index);42                  }}43                >44                  {children}45                </button>46              );47            }48            return (49              <a href={href} target="_blank" rel="noopener noreferrer" {...props}>50                {children}51              </a>52            );53          },54        }}55      >56        {prepareCitations(content)}57      </ReactMarkdown>58    </div>59  );60});61