From 601237bbbfe5cfe194969a395c84c72385196799 Mon Sep 17 00:00:00 2001 From: team3 Date: Fri, 12 Jun 2026 08:10:36 +0200 Subject: [PATCH] Frontend: globales markdown.css statt 4 CSS-Duplikaten Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/src/assets/markdown.css | 73 +++++++++++++++++++ frontend/src/components/ElementSuggestion.vue | 30 +------- frontend/src/components/ElementsOverview.vue | 37 +--------- frontend/src/components/ElementsSidebar.vue | 39 +--------- frontend/src/components/TopicDetail.vue | 66 +---------------- frontend/src/main.js | 1 + 6 files changed, 81 insertions(+), 165 deletions(-) create mode 100644 frontend/src/assets/markdown.css diff --git a/frontend/src/assets/markdown.css b/frontend/src/assets/markdown.css new file mode 100644 index 0000000..601c8a5 --- /dev/null +++ b/frontend/src/assets/markdown.css @@ -0,0 +1,73 @@ +/* Gemeinsames Markdown-Styling für v-html-Inhalte (renderMarkdown). + v-html-Kinder tragen keine data-v-Attribute — daher globale Regeln statt + :deep()-Kopien in jeder Komponente. Komponenten-Overrides bleiben scoped + und gewinnen per Spezifität (z. B. pre-Scroll in TopicDetail). */ + +.markdown p { + margin: 0 0 0.5em; +} + +.markdown p:last-child { + margin-bottom: 0; +} + +.markdown ul, +.markdown ol { + margin: 0.3em 0; + padding-left: 1.2em; +} + +.markdown li { + margin: 0.15em 0; +} + +.markdown code { + background: var(--border); + padding: 1px 4px; + border-radius: 4px; + font-family: "SF Mono", Consolas, monospace; + font-size: 0.85em; + /* Lange Bezeichner (Namespaces, Pfade) dürfen umbrechen statt zu überlaufen */ + overflow-wrap: anywhere; +} + +.markdown pre { + background: var(--code-bg, #1e2330); + color: var(--code-fg, #e6e8ee); + padding: 10px 12px; + border-radius: 8px; + /* Default: umbrechen (schmale Sidebars/Karten) — die breite Lese-Ansicht + in TopicDetail überschreibt auf horizontales Scrollen */ + white-space: pre-wrap; + overflow-wrap: anywhere; + margin: 0.5em 0; +} + +.markdown pre code { + background: none; + padding: 0; + color: inherit; + font-size: 0.85em; +} + +.markdown h1, +.markdown h2, +.markdown h3 { + font-size: 0.95em; + margin: 0.6em 0 0.3em; +} + +.markdown a { + color: var(--accent-hover); +} + +.markdown table { + border-collapse: collapse; + font-size: 0.95em; +} + +.markdown th, +.markdown td { + border: 1px solid var(--border-strong); + padding: 2px 6px; +} diff --git a/frontend/src/components/ElementSuggestion.vue b/frontend/src/components/ElementSuggestion.vue index acd6532..bebd653 100644 --- a/frontend/src/components/ElementSuggestion.vue +++ b/frontend/src/components/ElementSuggestion.vue @@ -175,38 +175,10 @@ function submit() { cursor: not-allowed; } -/* Markdown in der Vorschau */ -.markdown :deep(p) { - margin: 0 0 0.4em; -} - -.markdown :deep(p:last-child) { - margin-bottom: 0; -} - -.markdown :deep(code) { - background: var(--border); - padding: 1px 4px; - border-radius: 4px; - font-family: "SF Mono", Consolas, monospace; - font-size: 0.85em; - overflow-wrap: anywhere; -} - +/* Markdown: Basis global (assets/markdown.css); kompakte Vorschau-Code-Blöcke */ .markdown :deep(pre) { - background: var(--code-bg, #1e2330); - color: var(--code-fg, #e6e8ee); padding: 6px 8px; border-radius: 6px; - white-space: pre-wrap; - overflow-wrap: anywhere; margin: 0.3em 0; } - -.markdown :deep(pre code) { - background: none; - padding: 0; - color: inherit; - font-size: 0.85em; -} diff --git a/frontend/src/components/ElementsOverview.vue b/frontend/src/components/ElementsOverview.vue index 719170f..1f0d991 100644 --- a/frontend/src/components/ElementsOverview.vue +++ b/frontend/src/components/ElementsOverview.vue @@ -161,45 +161,10 @@ function plain(text) { margin-bottom: 0.2rem; } -/* Markdown im Guide-Stil */ +/* Markdown: Basis global (assets/markdown.css), hier nur Grundschrift der Karten */ .markdown { font-size: 0.9rem; line-height: 1.55; color: var(--text); } - -.markdown :deep(p) { - margin: 0 0 0.5em; -} - -.markdown :deep(p:last-child) { - margin-bottom: 0; -} - -.markdown :deep(code) { - background: var(--border); - padding: 1px 4px; - border-radius: 4px; - font-family: "SF Mono", Consolas, monospace; - font-size: 0.85em; - overflow-wrap: anywhere; -} - -.markdown :deep(pre) { - background: var(--code-bg, #1e2330); - color: var(--code-fg, #e6e8ee); - padding: 10px 12px; - border-radius: 8px; - /* Umbrechen statt horizontal scrollen — Scrollbar verdeckt sonst die Code-Zeile */ - white-space: pre-wrap; - overflow-wrap: anywhere; - margin: 0.4em 0; -} - -.markdown :deep(pre code) { - background: none; - padding: 0; - color: inherit; - font-size: 0.85em; -} diff --git a/frontend/src/components/ElementsSidebar.vue b/frontend/src/components/ElementsSidebar.vue index 18a702e..399bb03 100644 --- a/frontend/src/components/ElementsSidebar.vue +++ b/frontend/src/components/ElementsSidebar.vue @@ -801,46 +801,9 @@ async function send() { margin: 0; } -/* --- Markdown im Guide-Stil (Muster: TopicDetail) --- */ -.markdown :deep(p) { - margin: 0 0 0.5em; -} - -.markdown :deep(p:last-child) { - margin-bottom: 0; -} - -.markdown :deep(ul), -.markdown :deep(ol) { - margin: 0.3em 0; - padding-left: 1.2em; -} - -.markdown :deep(code) { - background: var(--border); - padding: 1px 4px; - border-radius: 4px; - font-family: "SF Mono", Consolas, monospace; - font-size: 0.85em; - overflow-wrap: anywhere; -} - +/* Markdown: Basis global (assets/markdown.css); schmale Sidebar → kompaktere Code-Blöcke */ .markdown :deep(pre) { - background: var(--code-bg, #1e2330); - color: var(--code-fg, #e6e8ee); padding: 8px 10px; - border-radius: 8px; - /* Schmale Sidebar: Code umbrechen statt horizontal scrollen */ - white-space: pre-wrap; - overflow-wrap: anywhere; - margin: 0.4em 0; -} - -.markdown :deep(pre code) { - background: none; - padding: 0; - color: inherit; - font-size: 0.85em; } /* --- KI-Prüfung --- */ diff --git a/frontend/src/components/TopicDetail.vue b/frontend/src/components/TopicDetail.vue index f674b98..416cba3 100644 --- a/frontend/src/components/TopicDetail.vue +++ b/frontend/src/components/TopicDetail.vue @@ -498,56 +498,13 @@ async function send() { color: var(--text-muted); } -/* --- Markdown (Sections + Chat) --- */ -.markdown :deep(p) { - margin: 0 0 0.5em; -} - -.markdown :deep(p:last-child) { - margin-bottom: 0; -} - -.markdown :deep(ul), -.markdown :deep(ol) { - margin: 0.3em 0; - padding-left: 1.2em; -} - -.markdown :deep(li) { - margin: 0.15em 0; -} - -.markdown :deep(code) { - background: var(--border); - padding: 1px 4px; - border-radius: 4px; - font-family: "SF Mono", Consolas, monospace; - font-size: 0.85em; - /* Lange Bezeichner (Namespaces, Pfade) dürfen umbrechen statt zu überlaufen */ - overflow-wrap: anywhere; -} +/* --- Markdown: Basis global (assets/markdown.css), hier nur Lese-Ansicht-Overrides --- */ +/* Breite Lese-Ansicht: Code scrollt horizontal statt umzubrechen */ .markdown :deep(pre) { - background: var(--code-bg, #1e2330); - color: var(--code-fg, #e6e8ee); - padding: 10px 12px; - border-radius: 8px; + white-space: pre; + overflow-wrap: normal; overflow-x: auto; - margin: 0.5em 0; -} - -.markdown :deep(pre code) { - background: none; - padding: 0; - color: inherit; - font-size: 0.85em; -} - -.markdown :deep(h1), -.markdown :deep(h2), -.markdown :deep(h3) { - font-size: 0.95em; - margin: 0.6em 0 0.3em; } /* „Beispiel"-Überschriften in Karten als dezentes Uppercase-Label */ @@ -559,21 +516,6 @@ async function send() { margin: 0.9em 0 0.35em; } -.markdown :deep(a) { - color: var(--accent-hover); -} - -.markdown :deep(table) { - border-collapse: collapse; - font-size: 0.95em; -} - -.markdown :deep(th), -.markdown :deep(td) { - border: 1px solid var(--border-strong); - padding: 2px 6px; -} - /* Lesbarkeit: ~17px Fließtext, Zeilenhöhe 1.6, Textspalte max. ~70 Zeichen — Code-Blöcke dürfen die volle Kartenbreite nutzen */ .section-body { diff --git a/frontend/src/main.js b/frontend/src/main.js index 01433bc..1e4e8f2 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -1,4 +1,5 @@ import { createApp } from 'vue' import App from './App.vue' +import './assets/markdown.css' createApp(App).mount('#app')