mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-07-18 14:55:21 +00:00
Fix the broken ESLint setup: add vue-eslint-parser and @typescript-eslint/parser and wire the TS parser into eslint.config.mjs so .ts and <script lang=ts> parse (was failing outright). Clear the resulting backlog to a clean 0/0 baseline — fix genuine issues, relax two intentional-pattern rules (multi-word-component-names, no-required-prop-with-default). Add a committed .githooks/pre-commit (enabled via core.hooksPath, auto-set by the prepare script) that runs Pint on staged PHP and ESLint --max-warnings 0 on staged resources/scripts JS/TS/Vue, blocking on failure. Add composer/npm lint scripts and document the gate in CLAUDE.md. Replace every scattered v-html with a single audited BaseSanitizedHtml component that DOMPurify-sanitizes its input (new utils/markdown.ts sanitizeHtml), so server/registry-provided HTML is actually sanitized and vue/no-v-html stays enabled everywhere but one reviewed sink.
43 lines
1.4 KiB
Vue
43 lines
1.4 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue'
|
|
import type { AiChatMessage } from '@/scripts/types/ai-config'
|
|
import { renderMarkdown } from '@/scripts/utils/markdown'
|
|
|
|
const props = defineProps<{
|
|
message: AiChatMessage
|
|
}>()
|
|
|
|
const isUser = computed(() => props.message.role === 'user')
|
|
|
|
// Assistant messages get rendered as markdown → sanitized HTML so GFM
|
|
// features (code blocks, lists, tables, inline formatting) display as
|
|
// the model intended. User messages stay as plain text because the
|
|
// user typed them verbatim and markdown syntax would be surprising.
|
|
const renderedHtml = computed(() =>
|
|
isUser.value ? '' : renderMarkdown(props.message.content ?? ''),
|
|
)
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
class="flex"
|
|
:class="isUser ? 'justify-end' : 'justify-start'"
|
|
>
|
|
<div
|
|
class="max-w-[85%] rounded-lg px-4 py-2 text-sm"
|
|
:class="
|
|
isUser
|
|
? 'bg-primary-500 text-white'
|
|
: 'bg-surface-tertiary text-body'
|
|
"
|
|
>
|
|
<p v-if="isUser" class="whitespace-pre-wrap break-words">
|
|
{{ message.content ?? '' }}
|
|
</p>
|
|
<!-- Assistant output is sanitized via DOMPurify in renderMarkdown
|
|
before it reaches v-html — see resources/scripts/utils/markdown.ts. -->
|
|
<BaseSanitizedHtml v-else class="prose prose-sm max-w-none break-words" :html="renderedHtml" />
|
|
</div>
|
|
</div>
|
|
</template>
|