From 619c93e28515d6fd32f6f5a5b7d8036760e34bcb Mon Sep 17 00:00:00 2001 From: SushritaSingh Date: Wed, 30 Jul 2025 12:01:49 +0530 Subject: [PATCH 1/3] feat: Add basic markdown rendering for AI responses #21 --- package.json | 113 ++++++++++++++++++------------------ src/App.tsx | 8 ++- src/components/Terminal.tsx | 37 ++++++++++++ tailwind.config.js | 2 +- 4 files changed, 101 insertions(+), 59 deletions(-) create mode 100644 src/components/Terminal.tsx diff --git a/package.json b/package.json index 28b328e..63a03ab 100644 --- a/package.json +++ b/package.json @@ -1,58 +1,59 @@ { - "name": "term", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc -b && vite build", - "lint": "eslint .", - "lint:fix": "eslint . --fix", - "preview": "vite preview", - "test": "vitest run", - "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,md}\"", - "format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx,css,md}\"", - "format:rust": "cd src-tauri && cargo fmt --all", - "format:all": "npm run format && npm run format:rust", - "prepare": "husky" - }, - "dependencies": { - "eslint-define-config": "^2.1.0", - "react": "^19.1.0", - "react-dom": "^19.1.0" - }, - "devDependencies": { - "@eslint/js": "^9.25.0", - "@tauri-apps/api": "^2.5.0", - "@tauri-apps/cli": "^2.5.0", - "@testing-library/jest-dom": "^6.6.3", - "@testing-library/react": "^16.3.0", - "@testing-library/user-event": "^14.6.1", - "@types/jest": "^29.5.14", - "@types/react": "^19.1.2", - "@types/react-dom": "^19.1.2", - "@vitejs/plugin-react": "^4.4.1", - "@vitest/coverage-v8": "3.1.4", - "autoprefixer": "^10.4.21", - "eslint": "^9.25.0", - "eslint-plugin-react": "^7.34.3", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.19", - "globals": "^16.0.0", - "husky": "^9.0.11", - "identity-obj-proxy": "^3.0.0", - "jest": "^29.7.0", - "jest-environment-jsdom": "^29.7.0", - "jsdom": "^26.1.0", - "lint-staged": "^16.0.0", - "postcss": "^8.5.3", - "prettier": "^3.2.5", - "tailwindcss": "^3.4.17", - "ts-jest": "^29.3.4", - "typescript": "~5.8.3", - "typescript-eslint": "^8.30.1", - "vite": "^6.3.5", - "vitest": "^3.1.4" - }, - "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977" + "name": "term", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "preview": "vite preview", + "test": "vitest run", + "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css,md}\"", + "format:check": "prettier --check \"src/**/*.{js,jsx,ts,tsx,css,md}\"", + "format:rust": "cd src-tauri && cargo fmt --all", + "format:all": "npm run format && npm run format:rust", + "prepare": "husky" + }, + "dependencies": { + "react": "^19.1.0", + "react-dom": "^19.1.0", + "react-markdown": "^8.0.7", + "eslint-define-config": "^2.1.0" + }, + "devDependencies": { + "@eslint/js": "^9.25.0", + "@tauri-apps/api": "^2.5.0", + "@tauri-apps/cli": "^2.5.0", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", + "@types/jest": "^29.5.14", + "@types/react": "^19.1.2", + "@types/react-dom": "^19.1.2", + "@vitejs/plugin-react": "^4.4.1", + "@vitest/coverage-v8": "3.1.4", + "autoprefixer": "^10.4.21", + "eslint": "^9.25.0", + "eslint-plugin-react": "^7.34.3", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.19", + "globals": "^16.0.0", + "husky": "^9.0.11", + "identity-obj-proxy": "^3.0.0", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "jsdom": "^26.1.0", + "lint-staged": "^16.0.0", + "postcss": "^8.5.6", + "prettier": "^3.2.5", + "tailwindcss": "^3.4.17", + "ts-jest": "^29.3.4", + "typescript": "~5.8.3", + "typescript-eslint": "^8.30.1", + "vite": "^6.3.5", + "vitest": "^3.1.4" + }, + "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977" } diff --git a/src/App.tsx b/src/App.tsx index 972ab60..330ab1a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,8 +1,12 @@ -import Terminal from './components/Terminal'; import './App.css'; +import Terminal from './components/Terminal'; function App() { - return ; + return ( +
+ +
+ ); } export default App; diff --git a/src/components/Terminal.tsx b/src/components/Terminal.tsx new file mode 100644 index 0000000..8cb0db5 --- /dev/null +++ b/src/components/Terminal.tsx @@ -0,0 +1,37 @@ +import { useState } from 'react'; +import ReactMarkdown from 'react-markdown'; + +interface Message { + type: 'command'|'output'|'error'|'llm'; + text: string; +} + +export default function Terminal() { + const [messages] = useState([ + { + type: 'llm', + text: '**Welcome!**\n\n_Everything you type will render as Markdown._\n\nTry list:\n- Item 1\n- Item 2\n\nCode:\n```\necho hello\n```' + } + ]); + + return ( +
+
+ {messages.map((msg, idx) => ( +
+ {msg.type === 'llm' + ? {msg.text} + : msg.text} +
+ ))} +
+
+ +
+
+ ); +} diff --git a/tailwind.config.js b/tailwind.config.js index 57beddd..dde18eb 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -15,7 +15,7 @@ export default { error: '#e06c75', llm: '#98c379', prompt: '#61afef', - border: '#333', + border: '#333' } }, fontFamily: { From 6c626915659099d10ae32de1b46efd4ce87e471b Mon Sep 17 00:00:00 2001 From: SushritaSingh Date: Wed, 30 Jul 2025 12:16:23 +0530 Subject: [PATCH 2/3] feat: Add basic markdown rendering for AI responses #21 --- term | 1 + 1 file changed, 1 insertion(+) create mode 160000 term diff --git a/term b/term new file mode 160000 index 0000000..f400914 --- /dev/null +++ b/term @@ -0,0 +1 @@ +Subproject commit f400914daeab6e6ecf703d454979c5c1ac22598b From a8975d34a78bc74f014f9716bb5bbf6b5ce0683a Mon Sep 17 00:00:00 2001 From: SushritaSingh Date: Fri, 1 Aug 2025 11:21:39 +0530 Subject: [PATCH 3/3] fix: add markdown rendering and malformed markdown handling --- src/App.tsx | 29 ++++++++++++++-- src/components/Terminal.tsx | 66 ++++++++++++++++++++++++++++--------- 2 files changed, 77 insertions(+), 18 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 330ab1a..a082965 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,33 @@ -import './App.css'; +import './App.css'; import Terminal from './components/Terminal'; +const exampleResponse = ` +# AI Summary +Here is some **bold text** and *italic text*. + +- Bullet Point 1 +- Bullet Point 2 + +\`\`\`javascript +console.log("Code block test"); +\`\`\` + +⚠️ Error Message: +\x1b[31merror\x1b[0m Something went wrong! +`; + +const malformedResponse = ` +### Unclosed *italic* +**Bold without closing +- List item +`; + function App() { return ( -
- +
+ {/* ✅ Use both to remove warning and test */} + +
); } diff --git a/src/components/Terminal.tsx b/src/components/Terminal.tsx index 8cb0db5..28ca478 100644 --- a/src/components/Terminal.tsx +++ b/src/components/Terminal.tsx @@ -2,32 +2,68 @@ import { useState } from 'react'; import ReactMarkdown from 'react-markdown'; interface Message { - type: 'command'|'output'|'error'|'llm'; + type: 'command' | 'output' | 'error' | 'llm'; text: string; } -export default function Terminal() { - const [messages] = useState([ - { - type: 'llm', - text: '**Welcome!**\n\n_Everything you type will render as Markdown._\n\nTry list:\n- Item 1\n- Item 2\n\nCode:\n```\necho hello\n```' - } - ]); +interface TerminalProps { + aiResponse?: string; // ✅ Optional prop +} + +// ✅ Function to strip ANSI escape codes +function stripAnsi(input: string): string { + return input.replace(/\x1b\[[0-9;]*m/g, ''); +} + +export default function Terminal({ aiResponse }: TerminalProps) { + // ✅ Initialize state properly with lazy function to avoid re-runs + const [messages] = useState(() => + aiResponse + ? [{ type: 'llm', text: aiResponse }] + : [ + { + type: 'llm', + text: ` +# AI Response Example +This is **bold**, _italic_, and a list: + +- First item +- Second item + +Code block: +\`\`\`javascript +console.log("Hello Markdown!"); +\`\`\` + +⚠️ Error Test: +\x1b[31merror\x1b[0m Something went wrong! + +### Malformed Markdown Test +**Bold without close +_Unclosed italic +`, + }, + ] + ); return ( -
-
+
+
{messages.map((msg, idx) => (
- {msg.type === 'llm' - ? {msg.text} - : msg.text} + {msg.type === 'llm' ? ( + + {stripAnsi(msg.text)} + + ) : ( + msg.text + )}
))}
-
+