mirror of
https://github.com/Mintplex-Labs/anything-llm.git
synced 2024-11-18 20:20:11 +01:00
add codeblock support for prompt replies and historical messages (#55)
* add codeblock support for prompt replies and historical messages add markdown-it * Fix spacing for HTML rendering
This commit is contained in:
parent
bd32f97a21
commit
2403806949
7662
frontend/package-lock.json
generated
Normal file
7662
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -15,6 +15,7 @@
|
||||
"@metamask/jazzicon": "^2.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"he": "^1.2.0",
|
||||
"markdown-it": "^13.0.1",
|
||||
"pluralize": "^8.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-device-detect": "^2.2.2",
|
||||
|
@ -119,9 +119,7 @@ export default function ManageWorkspace({ hideModal = noop, workspace }) {
|
||||
setSelectFiles([...new Set(updatedDocs)]);
|
||||
} else {
|
||||
var newDocs = [];
|
||||
var parentDirs = directories.items.find(
|
||||
(item) => item.name === parent
|
||||
)
|
||||
var parentDirs = directories.items.find((item) => item.name === parent);
|
||||
if (isFolder && parentDirs) {
|
||||
const folderItems = parentDirs.items;
|
||||
newDocs = folderItems.map((item) => parent + "/" + item.name);
|
||||
|
@ -3,6 +3,7 @@ import { AlertTriangle } from "react-feather";
|
||||
import Jazzicon from "../../../../UserIcon";
|
||||
import { v4 } from "uuid";
|
||||
import { decode as HTMLDecode } from "he";
|
||||
import renderMarkdown from "../../../../../utils/chat/markdown";
|
||||
|
||||
function HistoricalMessage({
|
||||
message,
|
||||
@ -52,9 +53,10 @@ function HistoricalMessage({
|
||||
<div ref={replyRef} className="flex justify-start items-end mb-4">
|
||||
<Jazzicon size={30} user={{ uid: workspace.slug }} />
|
||||
<div className="ml-2 py-3 px-4 max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-t-2xl rounded-br-2xl rounded-bl-sm">
|
||||
<span className="whitespace-pre-line text-slate-800 dark:text-slate-200 font-semibold">
|
||||
{message}
|
||||
</span>
|
||||
<span
|
||||
className="whitespace-pre-line text-slate-800 dark:text-slate-200 font-semibold flex flex-col gap-y-1"
|
||||
dangerouslySetInnerHTML={{ __html: renderMarkdown(message) }}
|
||||
/>
|
||||
<Citations sources={sources} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { memo, useEffect, useRef, useState } from "react";
|
||||
import { AlertTriangle } from "react-feather";
|
||||
import Jazzicon from "../../../../UserIcon";
|
||||
import { decode as HTMLDecode } from "he";
|
||||
import { v4 } from "uuid";
|
||||
import { decode as HTMLDecode } from "he";
|
||||
import renderMarkdown from "../../../../../utils/chat/markdown";
|
||||
|
||||
function PromptReply({
|
||||
uuid,
|
||||
@ -54,14 +55,14 @@ function PromptReply({
|
||||
<div
|
||||
key={uuid}
|
||||
ref={replyRef}
|
||||
className="chat__message mb-4 flex justify-start items-end"
|
||||
className="mb-4 flex justify-start items-end"
|
||||
>
|
||||
<Jazzicon size={30} user={{ uid: workspace.slug }} />
|
||||
<div className="ml-2 py-3 px-4 max-w-[75%] bg-orange-100 dark:bg-stone-700 rounded-t-2xl rounded-br-2xl rounded-bl-sm">
|
||||
<p className="text-[15px] whitespace-pre-line break-words text-slate-800 dark:text-slate-200 font-semibold">
|
||||
{reply}
|
||||
{!closed && <i className="not-italic blink">|</i>}
|
||||
</p>
|
||||
<span
|
||||
className="whitespace-pre-line text-slate-800 dark:text-slate-200 font-semibold flex flex-col gap-y-1"
|
||||
dangerouslySetInnerHTML={{ __html: renderMarkdown(reply) }}
|
||||
/>
|
||||
<Citations sources={sources} />
|
||||
</div>
|
||||
</div>
|
||||
|
36
frontend/src/utils/chat/markdown.js
Normal file
36
frontend/src/utils/chat/markdown.js
Normal file
@ -0,0 +1,36 @@
|
||||
import { encode as HTMLEncode } from "he";
|
||||
import markdownIt from "markdown-it";
|
||||
const markdown = markdownIt({
|
||||
html: true,
|
||||
typographer: true,
|
||||
highlight: function (str) {
|
||||
return `<div class="whitespace-pre-line w-fit rounded-lg bg-black-900 px-4 pt-10 pb-4 relative font-mono font-normal text-sm text-slate-200"><div class="w-full flex items-center absolute top-0 left-0 text-slate-200 bg-stone-800 px-4 py-2 text-xs font-sans justify-between rounded-t-md"><button onclick='window.copySnippet();' class="flex ml-auto gap-2"><svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24" stroke-linecap="round" stroke-linejoin="round" class="h-4 w-4" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>Copy code</button></div><pre class='markdown'>${HTMLEncode(
|
||||
str
|
||||
)}<pre></div>`;
|
||||
},
|
||||
});
|
||||
|
||||
window.copySnippet = function () {
|
||||
if (!event?.target) return false;
|
||||
|
||||
const target = event?.target;
|
||||
const markdown =
|
||||
target.parentElement?.parentElement?.querySelector(".markdown")?.innerText;
|
||||
if (!markdown) return false;
|
||||
|
||||
window.navigator.clipboard.writeText(markdown);
|
||||
target.classList.add("text-green-500");
|
||||
const originalText = target.innerHTML;
|
||||
target.innerText = "Copied!";
|
||||
target.setAttribute("disabled", true);
|
||||
|
||||
setTimeout(() => {
|
||||
target.classList.remove("text-green-500");
|
||||
target.innerHTML = originalText;
|
||||
target.removeAttribute("disabled");
|
||||
}, 5000);
|
||||
};
|
||||
|
||||
export default function renderMarkdown(text) {
|
||||
return markdown.render(text);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -61,11 +61,13 @@ apiRouter.post("/v/:command", async (request, response) => {
|
||||
app.use("/api", apiRouter);
|
||||
|
||||
if (process.env.NODE_ENV !== "development") {
|
||||
app.use(express.static(path.resolve(__dirname, 'public'), {extensions: ["js"]}));
|
||||
app.use(
|
||||
express.static(path.resolve(__dirname, "public"), { extensions: ["js"] })
|
||||
);
|
||||
|
||||
app.use("/", function (_, response) {
|
||||
response.sendFile(path.join(__dirname, "public", "index.html"));
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
app.all("*", function (_, response) {
|
||||
|
@ -26,8 +26,9 @@ function curateLanceSources(sources = []) {
|
||||
}
|
||||
|
||||
const LanceDb = {
|
||||
uri: `${!!process.env.STORAGE_DIR ? `${process.env.STORAGE_DIR}/` : "./storage/"
|
||||
}lancedb`,
|
||||
uri: `${
|
||||
!!process.env.STORAGE_DIR ? `${process.env.STORAGE_DIR}/` : "./storage/"
|
||||
}lancedb`,
|
||||
name: "LanceDb",
|
||||
connect: async function () {
|
||||
if (process.env.VECTOR_DB !== "lancedb")
|
||||
|
Loading…
Reference in New Issue
Block a user