mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-07-16 22:05:20 +00:00
The AI chat drawer was rendering assistant responses as plain text, so code blocks, lists, tables and inline formatting came through as literal asterisks and backticks — noisy and hard to scan. Adds a shared renderMarkdown() helper in resources/scripts/utils/ markdown.ts that parses GFM markdown via marked and sanitizes the result with DOMPurify before handing it to Vue's v-html. AiChatMessage uses the helper for assistant messages only; user messages stay as plain text since markdown syntax in their own typed input would be surprising. Assistant bubbles get the Tailwind `prose prose-sm` classes from the already-enabled @tailwindcss/typography plugin so headings, lists and code blocks inherit sensible defaults without per-element styling. Security: DOMPurify runs in its default browser profile, which strips <script>, event handlers, javascript: URLs and every other XSS vector. The AI provider isn't a trusted source — it can echo arbitrary user input and tool-call results from the database — so sanitization is non-negotiable even though the immediate source is our own backend.
68 lines
1.8 KiB
JSON
68 lines
1.8 KiB
JSON
{
|
|
"private": true,
|
|
"engines": {
|
|
"node": ">=24"
|
|
},
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "vite",
|
|
"watch": "vite build --watch",
|
|
"build": "vite build",
|
|
"serve": "vite preview",
|
|
"test": "eslint ./resources/scripts"
|
|
},
|
|
"devDependencies": {
|
|
"@tailwindcss/forms": "^0.5.10",
|
|
"@tailwindcss/typography": "^0.5.16",
|
|
"@tailwindcss/vite": "^4.0.0",
|
|
"@types/lodash": "^4.17.24",
|
|
"@vitejs/plugin-vue": "^6.0.0",
|
|
"@vue/compiler-sfc": "^3.5.13",
|
|
"eslint": "^10.0.0",
|
|
"eslint-config-prettier": "^10.0.0",
|
|
"eslint-plugin-vue": "^10.0.0",
|
|
"prettier": "^3.4.2",
|
|
"tailwind-scrollbar": "^4.0.0",
|
|
"tailwindcss": "^4.0.0",
|
|
"typescript": "^6.0.2",
|
|
"vue-tsc": "^3.2.6"
|
|
},
|
|
"dependencies": {
|
|
"@headlessui/vue": "^1.7.23",
|
|
"@heroicons/vue": "^2.2.0",
|
|
"@popperjs/core": "^2.11.8",
|
|
"@stripe/stripe-js": "^2.4.0",
|
|
"@tiptap/core": "^3.0.0",
|
|
"@tiptap/extension-text-align": "^3.0.0",
|
|
"@tiptap/pm": "^3.0.0",
|
|
"@tiptap/starter-kit": "^3.0.0",
|
|
"@tiptap/vue-3": "^3.0.0",
|
|
"@types/node": "^24.0.0",
|
|
"@vuelidate/components": "^1.2.6",
|
|
"@vuelidate/core": "^2.0.3",
|
|
"@vuelidate/validators": "^2.0.4",
|
|
"@vueuse/core": "^14.0.0",
|
|
"axios": "1.14.0",
|
|
"chart.js": "^4.5.1",
|
|
"date-fns": "^4.1.0",
|
|
"dompurify": "^3.3.3",
|
|
"guid": "^0.0.12",
|
|
"laravel-vite-plugin": "^3.0.0",
|
|
"lodash": "^4.17.21",
|
|
"marked": "^18.0.0",
|
|
"maska": "^3.0.4",
|
|
"mini-svg-data-uri": "^1.4.4",
|
|
"moment": "^2.30.1",
|
|
"path": "^0.12.7",
|
|
"pinia": "^3.0.0",
|
|
"v-money3": "^3.24.1",
|
|
"v-tooltip": "^4.0.0-beta.17",
|
|
"vite": "^8.0.0",
|
|
"vue": "^3.5",
|
|
"vue-flatpickr-component": "^12.0.0",
|
|
"vue-i18n": "^11.0.1",
|
|
"vue-router": "^5.0.0",
|
|
"vuedraggable": "^4.1.0"
|
|
}
|
|
}
|