diff --git a/package.json b/package.json
index 1cf2d45f..903e7930 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"lodash-es": "^4.17.21",
"mermaid": "^10.8.0",
"nanoid": "^5.0.5",
+ "nomnoml": "^1.6.2",
"openai": "^4.26.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d1a43a50..bbbc2a54 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -74,6 +74,9 @@ dependencies:
nanoid:
specifier: ^5.0.5
version: 5.0.5
+ nomnoml:
+ specifier: ^1.6.2
+ version: 1.6.2
openai:
specifier: ^4.26.1
version: 4.26.1
@@ -6564,6 +6567,10 @@ packages:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
dev: true
+ /graphre@0.1.3:
+ resolution: {integrity: sha512-F4OO/+BQj3R2UB3PQOGLgdAUy+SQuwy2A5cVGELAQDJlloSyyHqRe60ESFouRf8W0K+sm6gtWKotOwZoX3BL8w==}
+ dev: false
+
/has-bigints@1.0.2:
resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==}
dev: true
@@ -8378,6 +8385,13 @@ packages:
vm-browserify: 1.1.2
dev: true
+ /nomnoml@1.6.2:
+ resolution: {integrity: sha512-R3dA3FS8txilobpd2ZdnCuEwmXYYljxza2wR41YE/cIHMbt0eXsjlXHlAsD+F/fVe536f0WkAQ+VQFRC3hPZCA==}
+ hasBin: true
+ dependencies:
+ graphre: 0.1.3
+ dev: false
+
/non-layered-tidy-tree-layout@2.0.2:
resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==}
dev: false
@@ -10723,6 +10737,7 @@ packages:
/workbox-google-analytics@7.0.0:
resolution: {integrity: sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==}
+ deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained
dependencies:
workbox-background-sync: 7.0.0
workbox-core: 7.0.0
diff --git a/src/components/Markdown.tsx b/src/components/Markdown.tsx
index f2d7aca1..67f27981 100644
--- a/src/components/Markdown.tsx
+++ b/src/components/Markdown.tsx
@@ -17,6 +17,7 @@ import oneLight from "react-syntax-highlighter/dist/esm/styles/hljs/atom-one-lig
import CodeHeader from "./CodeHeader";
import HtmlPreview from "./HtmlPreview";
import MermaidPreview from "./MermaidPreview";
+import NomnomlPreview from "./NomnomlPreview";
const fixLanguageName = (language: string | null) => {
if (!language) {
@@ -108,6 +109,10 @@ function Markdown({
preview = (
);
+ } else if (language === "nomnoml") {
+ preview = (
+
+ );
}
}
diff --git a/src/components/Message/AppMessage/Instructions.tsx b/src/components/Message/AppMessage/Instructions.tsx
index c1ae0b30..f4be6eee 100644
--- a/src/components/Message/AppMessage/Instructions.tsx
+++ b/src/components/Message/AppMessage/Instructions.tsx
@@ -29,7 +29,7 @@ We think ChatCraft is the best platform for learning, experimenting, and getting
| ------------------------------------- |:---------:|:-------:|:-------:|
| Optimized for conversations about code | ✅ | ❌ | ❌ |
| Work with models from multiple AI vendors | ✅ |❌ | ❌ |
-| Previews for Mermaid Diagrams, HTML | ✅ | ❌ | ❌ |
+| Previews for Mermaid/Nomnoml Diagrams, HTML | ✅ | ❌ | ❌ |
| Edit Generated AI Replies | ✅ | ❌ | ✅ |
| Use Custom System Prompts | ✅ | ✅ | ❌ |
| Easy to retry with different AI models| ✅ | ❌ | ❌ |
diff --git a/src/components/NomnomlPreview.tsx b/src/components/NomnomlPreview.tsx
new file mode 100644
index 00000000..a9e1e14c
--- /dev/null
+++ b/src/components/NomnomlPreview.tsx
@@ -0,0 +1,85 @@
+import { memo, useCallback, useEffect, useRef, type ReactNode } from "react";
+import { Card, CardBody, IconButton, useClipboard } from "@chakra-ui/react";
+import { TbCopy } from "react-icons/tb";
+import { useAlert } from "../hooks/use-alert";
+
+type NomnomlPreviewProps = {
+ children: ReactNode & ReactNode[];
+};
+
+const NomnomlPreview = ({ children }: NomnomlPreviewProps) => {
+ const { onCopy, value, setValue } = useClipboard("");
+ const { info } = useAlert();
+ const diagramRef = useRef(null);
+ const code = String(children);
+
+ const handleCopy = useCallback(() => {
+ onCopy();
+ info({
+ title: "Copied to Clipboard",
+ message: "Nomnoml SVG diagram was copied to your clipboard.",
+ });
+ }, [onCopy, info]);
+
+ // Render the diagram as an SVG into our card's body
+ useEffect(() => {
+ const diagramDiv = diagramRef.current;
+ if (!diagramDiv) {
+ return;
+ }
+
+ const fetchNomnoml = async () => {
+ try {
+ // Load nomnoml dynamically at runtime if needed
+ const nomnoml = await import("nomnoml");
+ const svg = await nomnoml.renderSvg(code);
+
+ setValue(svg);
+
+ // Render nomnoml svg if successful
+ diagramDiv.innerHTML = svg;
+
+ // Adjust the width of the SVG to fit the content inside the CardBody
+ const svgElement = diagramDiv.querySelector("svg");
+ if (svgElement) {
+ svgElement.style.width = "100%";
+ }
+ } catch (err: any) {
+ // When the diagram fails, use the error vs. diagram for copying (to debug)
+ setValue(err);
+
+ // Render custom error message instead of error or blank content
+ const errMessage = `Error rendering Nomnoml diagram`;
+ diagramDiv.innerHTML = errMessage;
+ console.warn(`Error rendering nomnoml diagram`, err);
+ }
+ };
+ fetchNomnoml();
+ }, [diagramRef, code, setValue]);
+
+ return (
+
+ }
+ color="gray.600"
+ _dark={{ color: "gray.300" }}
+ variant="ghost"
+ onClick={() => handleCopy()}
+ isDisabled={!value}
+ />
+
+
+
+
+
+ );
+};
+
+// Memoize to reduce re-renders/flickering when content hasn't changed
+export default memo(NomnomlPreview);
diff --git a/src/lib/system-prompt.ts b/src/lib/system-prompt.ts
index d28e3fad..1c2d894a 100644
--- a/src/lib/system-prompt.ts
+++ b/src/lib/system-prompt.ts
@@ -8,7 +8,7 @@ I follow these rules when responding:
- Use GitHub flavored Markdown
- ALWAYS include the programming language name (js) or type of data (csv) at the start of Markdown code blocks
- Format ALL lines of code to 80 characters or fewer
-- Use Mermaid diagrams when discussing visual topics
+- Use Nomnoml or Mermaid diagrams when discussing visual topics
- If using functions, only use the specific functions I have been provided with
- If responding with math markdown, inline or otherwise, I use KaTeX syntax in math Markdown by enclosing EVERY mathematical expression, equation, variable, and formula with double-dollar signs \`($$)\`, for example: $$O(n\\log n)$$, $$1024 * 1024 = 1048576$$, $$1024^2$$, $$X$$
`;