Spaces:
Running
Running
File size: 3,885 Bytes
f098874 e4526cf 3717d81 727c614 f098874 e4526cf f098874 98a4631 e4526cf 3717d81 727c614 f098874 90b8b3b 8e65602 90b8b3b 0918045 e4526cf 5a19572 90b8b3b f098874 e4526cf 727c614 f098874 8e65602 4eeeb10 90b8b3b 4eeeb10 1ce4fbf 3717d81 1ce4fbf a155b02 2c7dc70 5a19572 2c7dc70 0918045 1ce4fbf 0918045 1ce4fbf f098874 727c614 4eeeb10 727c614 4eeeb10 727c614 4eeeb10 727c614 f098874 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | import Text from "../Text/Text";
import styles from "./Message.module.css";
import React, { useState, useEffect } from "react";
import { marked } from "marked";
import DOMPurify from "dompurify";
import UploadedFileCard from "../UploadedFileCard/UploadedFileCard";
interface MessageProps {
key: string;
textContent: string;
sender: "user" | "system";
openFileViewer?: (
fileUrl: string,
fileName: string,
page: number,
lines: string,
start: string,
) => void;
isStreaming?: boolean;
files?: { name: string; type: string; size: number }[];
}
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
function transformCitationsToLinks(text: string): string {
const citationRegex =
/\s*\[Source:\s*([^,]+?)\s*,\s*Page:\s*(\d+)\s*,\s*Lines:\s*(\d+\s*-\s*\d+)\s*,\s*Start:?\s*(\d+)\]/g;
return text.replace(citationRegex, (match, path, page, lines, start) => {
// const fileUrl = `https://the-ultimate-rag-hf-rag-integration-test.hf.space`+`\\viewer\\${path}`;
const fileUrl = `https://PopovDanil-backend.hf.space`+`\\viewer\\${path}`;
console.log(
"File URL:",
fileUrl,
"Page:",
page,
"Lines:",
lines,
"Start:",
start,
);
return ` <a id="${fileUrl}&${page}&${lines}&${start}" href="${fileUrl}" data-page="${page}" data-lines="${lines}" data-start="${start}">[Source]</a>`;
});
}
function Message(props: Readonly<MessageProps>) {
const { textContent, sender, openFileViewer, files } = props;
const messageBubbleStyle: string = `${styles.messageBox} ${sender === "user" ? styles.userMessageBox : styles.systemMessageBox}`;
const messageContainerStyle: string = `${styles.messageContainer} ${sender === "user" ? styles.userMessageContainer : styles.systemMessageContainer}`;
const [sanitizedHtml, setSanitizedHtml] = useState("");
useEffect(() => {
const parseAndSanitize = async () => {
const htmlResult = marked.parse(transformCitationsToLinks(textContent));
let finalHtml: string;
if (htmlResult instanceof Promise) {
finalHtml = await htmlResult;
} else {
finalHtml = htmlResult;
}
setSanitizedHtml(DOMPurify.sanitize(finalHtml));
};
parseAndSanitize();
}, [textContent]);
const handleContentClick = (event: React.MouseEvent<HTMLDivElement>) => {
const target = event.target as HTMLElement;
if (target.tagName === "A" && target.hasAttribute("href")) {
event.preventDefault();
const fileUrl = target.getAttribute("href");
const fileName = target.textContent ?? "";
const page = target.getAttribute("data-page");
const lines = target.getAttribute("data-lines");
const start = target.getAttribute("data-start");
console.log("File URL:", fileUrl, "Page:", page);
if (openFileViewer) {
openFileViewer(fileUrl ? fileUrl : '', fileName, parseInt(page ? page : "1"), lines ? lines : '1-1', start ? start : '');
console.log('Opening file preview:', fileUrl)
}
}
};
return (
<div className={messageContainerStyle}>
{files && files.length > 0 && (
<div className={styles.attachedFiles}>
{files.map((file, idx) => (
<UploadedFileCard
key={idx}
fileName={file.name}
fileType={file.type}
fileSize={file.size}
onClose={() => {}}
/>
))}
</div>
)}
<div className={messageBubbleStyle} onClick={handleContentClick}>
<Text
as="div"
interactable={true}
colorVariant={sender === "user" ? "button" : "primary"}
>
<span
className={styles.markdownContent}
dangerouslySetInnerHTML={{ __html: sanitizedHtml }}
/>
</Text>
</div>
</div>
);
}
export default Message;
|