From e7f98dd072721335fe70a8d27b33c4d4ca081026 Mon Sep 17 00:00:00 2001 From: marcus hinz Date: Tue, 21 Jul 2026 19:04:36 +0200 Subject: [PATCH] =?UTF-8?q?CSP:=20style-src=20ohne=20unsafe-inline=20?= =?UTF-8?q?=E2=80=94=20Fenster-Styles=20aus=20den=20HTML-K=C3=B6pfen=20nac?= =?UTF-8?q?h=20src/*-window.css?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit terminal/panel/popup.html laden ihre Styles jetzt als erste Imports der jeweiligen Entries (Kaskade wie zuvor: Fenster-CSS vor xterm/fonts); devCsp behält unsafe-inline für die Vite-HMR-Style-Injektion. --- panel.html | 368 ------------------------------- popup.html | 7 - src-tauri/tauri.conf.json | 2 +- src/panel-window.css | 366 +++++++++++++++++++++++++++++++ src/panel.ts | 1 + src/popup-window.css | 5 + src/popup.ts | 1 + src/terminal-window.css | 446 +++++++++++++++++++++++++++++++++++++ src/terminal.ts | 3 + terminal.html | 448 -------------------------------------- 10 files changed, 823 insertions(+), 824 deletions(-) create mode 100644 src/panel-window.css create mode 100644 src/popup-window.css create mode 100644 src/terminal-window.css diff --git a/panel.html b/panel.html index 92998cd..e324592 100644 --- a/panel.html +++ b/panel.html @@ -3,374 +3,6 @@ Dokument -
diff --git a/popup.html b/popup.html index d9d0323..0c1b393 100644 --- a/popup.html +++ b/popup.html @@ -3,13 +3,6 @@ Projekte -
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index a849634..d7e8225 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -13,7 +13,7 @@ "macOSPrivateApi": true, "windows": [], "security": { - "csp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src ipc: http://ipc.localhost", + "csp": "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; connect-src ipc: http://ipc.localhost", "devCsp": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src ipc: http://ipc.localhost ws://localhost:1420 http://localhost:1420" } }, diff --git a/src/panel-window.css b/src/panel-window.css new file mode 100644 index 0000000..00a3113 --- /dev/null +++ b/src/panel-window.css @@ -0,0 +1,366 @@ +/* Theme-Variablen — Defaults sind Mocha; applyTheme (themes.ts) überschreibt. */ +:root { + --bg: #1e1e2e; + --surface: #181825; + --tile: #11111b; + --line: #313244; + --line-strong: #45475a; + --text: #cdd6f4; + --muted: #a6adc8; + --faint: #6c7086; + --accent: #89b4fa; + --ok: #a6e3a1; + --warn: #f9e2af; + --err: #f38ba8; +} +html, +body { + height: 100%; + margin: 0; + background: var(--bg); + color: var(--text); + overflow: hidden; +} +body { + display: flex; + flex-direction: column; +} +/* Feiner Fensterrahmen fürs dekorationslose Fenster (nur Linux). */ +:root[data-platform="other"] body { + box-sizing: border-box; + border: 1px solid var(--line); +} +.panel-head { + flex: none; + display: flex; + flex-direction: column; + gap: 3px; + padding: 7px 8px 9px 14px; + background: var(--surface); + border-bottom: 1px solid var(--line); + font: + 500 12px/1 -apple-system, + system-ui, + sans-serif; + user-select: none; + -webkit-user-select: none; +} +.panel-titlerow { + display: flex; + align-items: center; + gap: 2px; + min-width: 0; +} +/* Kopfzeile wie der Terminal-Header: eigene Leiste voller Höhe mit + Tabs rechtsbündig vor den Fensterknöpfen (Andocken/Schließen). */ +.panel-topbar { + height: 40px; + flex: none; + display: flex; + align-items: center; + padding-left: 14px; + background: var(--surface); + border-bottom: 1px solid var(--line); + font: + 500 13px/1 -apple-system, + system-ui, + sans-serif; + user-select: none; + -webkit-user-select: none; + cursor: default; +} +.panel-topbar .panel-tabs { + margin-left: auto; +} +/* Fensterknöpfe rechts, volle Header-Höhe — wie im Terminal-Fenster. */ +.winbtn { + width: 44px; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + border: none; + background: transparent; + color: inherit; + cursor: default; + transition: background 0.12s ease; +} +.winbtn svg { + stroke: currentColor; + stroke-width: 1.2; + fill: none; + stroke-linecap: round; + stroke-linejoin: round; + opacity: 0.8; +} +.winbtn:hover { + background: var(--line); +} +.winbtn:hover svg { + opacity: 1; +} +.winbtn.close:hover { + background: var(--err); + color: var(--tile); +} +/* macOS hat native Fensterknöpfe — eigene Min/Max dort ausblenden. */ +:root[data-platform="mac"] .winbtn.osctl { + display: none; +} +/* Resize-Zonen für das dekorationslose Fenster (nur Linux). */ +#resize-grips { + display: none; +} +:root[data-platform="other"] #resize-grips { + display: block; +} +.grip { + position: fixed; + z-index: 100; +} +.grip.n { + top: 0; + left: 0; + right: 0; + height: 4px; + cursor: ns-resize; +} +.grip.s { + bottom: 0; + left: 0; + right: 0; + height: 4px; + cursor: ns-resize; +} +.grip.w { + top: 0; + bottom: 0; + left: 0; + width: 4px; + cursor: ew-resize; +} +.grip.e { + top: 0; + bottom: 0; + right: 0; + width: 4px; + cursor: ew-resize; +} +.grip.nw { + top: 0; + left: 0; + width: 9px; + height: 9px; + cursor: nwse-resize; + z-index: 101; +} +.grip.ne { + top: 0; + right: 0; + width: 9px; + height: 9px; + cursor: nesw-resize; + z-index: 101; +} +.grip.sw { + bottom: 0; + left: 0; + width: 9px; + height: 9px; + cursor: nesw-resize; + z-index: 101; +} +.grip.se { + bottom: 0; + right: 0; + width: 9px; + height: 9px; + cursor: nwse-resize; + z-index: 101; +} +.tab-sep { + width: 1px; + height: 16px; + background: var(--line-strong); + margin: 0 6px; + align-self: center; +} +.panel-actions { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 2px; +} +.panel-title { + flex: 0 1 auto; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: var(--muted); +} +.panel-title[contenteditable="true"] { + overflow: visible; + text-overflow: clip; + outline: none; + color: inherit; + cursor: text; +} +.panel-btn { + border: none; + background: transparent; + color: var(--muted); + cursor: default; + border-radius: 6px; + padding: 6px 9px; + font: inherit; + display: flex; + align-items: center; +} +.panel-btn:hover { + background: var(--line); + color: var(--text); +} +.panel-btn.copied { + color: var(--ok); +} +.panel-btn.error { + color: var(--err); +} +.panel-btn svg { + display: block; + stroke: currentColor; + stroke-width: 1.3; + fill: none; + stroke-linecap: round; + stroke-linejoin: round; +} +.panel-btn.active { + background: var(--line); + color: var(--text); +} +/* Aktiver Tab: Akzentfarbe + Unterstrich statt nur Flächenwechsel. */ +.panel-tabs .panel-btn.active { + background: transparent; + color: var(--accent); + border-radius: 0; + box-shadow: inset 0 -2px 0 currentColor; +} +.panel-btn.changed { + color: var(--warn); +} +.panel-editor { + flex: 1; + min-height: 0; + resize: none; + border: none; + outline: none; + padding: 16px 20px; + background: transparent; + color: inherit; + font-family: "JetBrains Mono", Menlo, monospace; + font-size: 12px; + line-height: 1.55; +} +.panel-editor[hidden] { + display: none; +} +.panel-tabs { + display: flex; + gap: 2px; +} +.panel-lang { + appearance: none; + -webkit-appearance: none; + margin-right: auto; + background: transparent; + color: var(--muted); + border: none; + border-radius: 6px; + padding: 6px 9px; + font: inherit; + cursor: default; +} +.panel-lang:hover { + background: var(--line); + color: var(--text); +} +#panel-content { + flex: 1; + min-height: 0; + overflow: auto; + padding: 16px 20px; + user-select: text; + -webkit-user-select: text; + cursor: text; + font-size: 13px; + line-height: 1.55; +} +#panel-content::-webkit-scrollbar { + width: 8px; +} +#panel-content::-webkit-scrollbar-thumb { + background: var(--line); + border-radius: 4px; +} +#panel-content.raw { + white-space: pre-wrap; + word-break: break-word; + font-family: "JetBrains Mono", Menlo, monospace; + font-size: 12px; +} +#panel-content.md h1, +#panel-content.md h2, +#panel-content.md h3 { + line-height: 1.25; + margin: 1em 0 0.4em; +} +#panel-content.md h1 { + font-size: 1.4em; +} +#panel-content.md h2 { + font-size: 1.2em; +} +#panel-content.md h3 { + font-size: 1.05em; +} +#panel-content.md :first-child { + margin-top: 0; +} +#panel-content.md p, +#panel-content.md ul, +#panel-content.md ol, +#panel-content.md pre, +#panel-content.md blockquote { + margin: 0 0 0.7em; +} +#panel-content.md code { + font-family: "JetBrains Mono", Menlo, monospace; + font-size: 0.9em; + background: var(--line); + border-radius: 4px; + padding: 1px 5px; +} +#panel-content.md pre { + background: var(--tile); + border-radius: 8px; + padding: 12px 14px; + overflow: auto; +} +#panel-content.md pre code { + background: none; + padding: 0; +} +#panel-content.md blockquote { + border-left: 3px solid var(--line); + padding-left: 12px; + color: var(--muted); +} +#panel-content.md a { + color: var(--accent); +} +.panel-btn[hidden], +.panel-lang[hidden], +#panel-content[hidden] { + display: none; +} diff --git a/src/panel.ts b/src/panel.ts index aee0bff..c66bf12 100644 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,3 +1,4 @@ +import "./panel-window.css"; import "@fontsource/jetbrains-mono/400.css"; import "@fontsource/jetbrains-mono/500.css"; import { invoke } from "@tauri-apps/api/core"; diff --git a/src/popup-window.css b/src/popup-window.css new file mode 100644 index 0000000..4e8a49d --- /dev/null +++ b/src/popup-window.css @@ -0,0 +1,5 @@ +html, +body { + margin: 0; + background: transparent; +} diff --git a/src/popup.ts b/src/popup.ts index f58cf85..76c3286 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -1,3 +1,4 @@ +import "./popup-window.css"; import { createApp } from "vue"; import Popup from "./components/Popup.vue"; import { i18n } from "./i18n"; diff --git a/src/terminal-window.css b/src/terminal-window.css new file mode 100644 index 0000000..705b268 --- /dev/null +++ b/src/terminal-window.css @@ -0,0 +1,446 @@ +/* Theme-Variablen — Defaults sind Mocha; applyTheme (themes.ts) überschreibt. */ +:root { + --bg: #1e1e2e; + --surface: #181825; + --tile: #11111b; + --line: #313244; + --line-strong: #45475a; + --text: #cdd6f4; + --muted: #a6adc8; + --faint: #6c7086; + --accent: #89b4fa; + --ok: #a6e3a1; + --warn: #f9e2af; + --err: #f38ba8; +} +html, +body { + height: 100%; + margin: 0; + background: var(--bg); + overflow: hidden; +} +body { + display: flex; + flex-direction: column; +} +/* Feiner Fensterrahmen fürs dekorationslose Fenster (nur Linux). */ +:root[data-platform="other"] body { + box-sizing: border-box; + border: 1px solid var(--line); +} +header { + height: 40px; + flex: none; + display: flex; + align-items: center; + gap: 10px; + /* Linux: schmaler Rand links; macOS: Ampel-Platz (Override unten) */ + padding: 0 0 0 16px; + background: var(--surface); + border-bottom: 1px solid var(--line); + color: var(--text); + font: + 500 13px/1 -apple-system, + system-ui, + sans-serif; + user-select: none; + -webkit-user-select: none; + cursor: default; +} +/* macOS: Platz links für die Ampel, eigene Fensterknöpfe aus. */ +:root[data-platform="mac"] header { + padding-left: 84px; + padding-right: 16px; +} +:root[data-platform="mac"] #winbtns { + display: none; +} +#project-icon { + width: 18px; + height: 18px; + border-radius: 4px; +} +#project-icon[hidden] { + display: none; +} +/* Tab-Leiste im Header: Befehle │ Dokument · Wiki · Suche. */ +header .panel-tabs { + margin-left: auto; +} +header .panel-tabs[hidden] { + display: none; +} +/* Ohne Tabs (Panel abgelöst) rückt das Pool-Badge selbst nach rechts. */ +header .panel-tabs[hidden] + #pool { + margin-left: auto; +} +.tab-sep { + width: 1px; + height: 16px; + background: var(--line-strong); + margin: 0 6px; + align-self: center; +} +#pool { + background: var(--line); + color: var(--muted); + border-radius: 999px; + padding: 4px 12px; + font-size: 11px; +} +#pool:empty { + display: none; +} +/* Eigene Fensterknöpfe (Linux): rechtsbündig, volle Header-Höhe. */ +#winbtns { + margin-left: 8px; + display: flex; + align-self: stretch; +} +#pool:empty + #winbtns { + margin-left: auto; +} +.winbtn { + width: 44px; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + border: none; + background: transparent; + color: inherit; + cursor: default; + transition: background 0.12s ease; +} +.winbtn svg { + stroke: currentColor; + stroke-width: 1.2; + opacity: 0.8; +} +.winbtn:hover { + background: var(--line); +} +.winbtn:hover svg { + opacity: 1; +} +.winbtn.close:hover { + background: var(--err); + color: var(--tile); +} +/* Resize-Zonen für das dekorationslose Fenster (nur Linux). */ +#resize-grips { + display: none; +} +:root[data-platform="other"] #resize-grips { + display: block; +} +.grip { + position: fixed; + z-index: 100; +} +.grip.n { + top: 0; + left: 0; + right: 0; + height: 4px; + cursor: ns-resize; +} +.grip.s { + bottom: 0; + left: 0; + right: 0; + height: 4px; + cursor: ns-resize; +} +.grip.w { + top: 0; + bottom: 0; + left: 0; + width: 4px; + cursor: ew-resize; +} +.grip.e { + top: 0; + bottom: 0; + right: 0; + width: 4px; + cursor: ew-resize; +} +.grip.nw { + top: 0; + left: 0; + width: 9px; + height: 9px; + cursor: nwse-resize; + z-index: 101; +} +.grip.ne { + top: 0; + right: 0; + width: 9px; + height: 9px; + cursor: nesw-resize; + z-index: 101; +} +.grip.sw { + bottom: 0; + left: 0; + width: 9px; + height: 9px; + cursor: nesw-resize; + z-index: 101; +} +.grip.se { + bottom: 0; + right: 0; + width: 9px; + height: 9px; + cursor: nwse-resize; + z-index: 101; +} +#body { + flex: 1; + min-height: 0; + display: flex; + flex-direction: row; +} +#term { + flex: 1; + min-width: 0; + min-height: 0; + padding: 12px 4px 12px 14px; +} +#term .xterm-viewport::-webkit-scrollbar { + width: 8px; +} +#term .xterm-viewport::-webkit-scrollbar-thumb { + background: var(--line); + border-radius: 4px; +} +#term .xterm-viewport::-webkit-scrollbar-track { + background: transparent; +} +/* Andockbares Panel rechts (nur sichtbar, wenn ein Entwurf ankommt). */ +#splitter { + flex: none; + width: 5px; + cursor: col-resize; + background: var(--line); +} +#panel { + flex: none; + width: 380px; + min-width: 0; + display: flex; + flex-direction: column; + background: var(--surface); + color: var(--text); +} +#panel[hidden], +#splitter[hidden] { + display: none; +} +.panel-head { + flex: none; + display: flex; + flex-direction: column; + gap: 2px; + padding: 6px 8px 8px 12px; + border-bottom: 1px solid var(--line); + font: + 500 12px/1 -apple-system, + system-ui, + sans-serif; + user-select: none; + -webkit-user-select: none; +} +.panel-titlerow { + display: flex; + align-items: center; + gap: 2px; + min-width: 0; +} +/* Ablösen/Ausblenden rechts in der Titelzeile — in jedem Modus da. */ +#panel-detach { + margin-left: auto; +} +.panel-actions { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 2px; +} +.panel-title { + flex: 0 1 auto; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: var(--muted); +} +.panel-title[contenteditable="true"] { + overflow: visible; + text-overflow: clip; + outline: none; + color: inherit; + cursor: text; +} +.panel-btn { + border: none; + background: transparent; + color: var(--muted); + cursor: default; + border-radius: 6px; + padding: 5px 8px; + font: inherit; + display: flex; + align-items: center; +} +.panel-btn:hover { + background: var(--line); + color: var(--text); +} +.panel-btn.copied { + color: var(--ok); +} +.panel-btn.error { + color: var(--err); +} +.panel-btn svg { + display: block; + stroke: currentColor; + stroke-width: 1.3; + fill: none; + stroke-linecap: round; + stroke-linejoin: round; +} +.panel-btn.active { + background: var(--line); + color: var(--text); +} +/* Aktiver Tab: Akzentfarbe + Unterstrich statt nur Flächenwechsel. */ +.panel-tabs .panel-btn.active { + background: transparent; + color: var(--accent); + border-radius: 0; + box-shadow: inset 0 -2px 0 currentColor; +} +.panel-btn.changed { + color: var(--warn); +} +.panel-editor { + flex: 1; + min-height: 0; + resize: none; + border: none; + outline: none; + padding: 14px 16px; + background: transparent; + color: inherit; + font-family: "JetBrains Mono", Menlo, monospace; + font-size: 12px; + line-height: 1.55; +} +.panel-editor[hidden] { + display: none; +} +.panel-tabs { + display: flex; + gap: 2px; +} +.panel-lang { + appearance: none; + -webkit-appearance: none; + margin-right: auto; + background: transparent; + color: var(--muted); + border: none; + border-radius: 6px; + padding: 6px 9px; + font: inherit; + cursor: default; +} +.panel-lang:hover { + background: var(--line); + color: var(--text); +} +#panel-content { + flex: 1; + min-height: 0; + overflow: auto; + padding: 14px 16px; + user-select: text; + -webkit-user-select: text; + cursor: text; + font-size: 13px; + line-height: 1.55; +} +#panel-content::-webkit-scrollbar { + width: 8px; +} +#panel-content::-webkit-scrollbar-thumb { + background: var(--line); + border-radius: 4px; +} +#panel-content.raw { + white-space: pre-wrap; + word-break: break-word; + font-family: "JetBrains Mono", Menlo, monospace; + font-size: 12px; +} +#panel-content.md h1, +#panel-content.md h2, +#panel-content.md h3 { + line-height: 1.25; + margin: 1em 0 0.4em; +} +#panel-content.md h1 { + font-size: 1.4em; +} +#panel-content.md h2 { + font-size: 1.2em; +} +#panel-content.md h3 { + font-size: 1.05em; +} +#panel-content.md :first-child { + margin-top: 0; +} +#panel-content.md p, +#panel-content.md ul, +#panel-content.md ol, +#panel-content.md pre, +#panel-content.md blockquote { + margin: 0 0 0.7em; +} +#panel-content.md code { + font-family: "JetBrains Mono", Menlo, monospace; + font-size: 0.9em; + background: var(--line); + border-radius: 4px; + padding: 1px 5px; +} +#panel-content.md pre { + background: var(--tile); + border-radius: 8px; + padding: 12px 14px; + overflow: auto; +} +#panel-content.md pre code { + background: none; + padding: 0; +} +#panel-content.md blockquote { + border-left: 3px solid var(--line); + padding-left: 12px; + color: var(--muted); +} +#panel-content.md a { + color: var(--accent); +} +.panel-btn[hidden], +.panel-lang[hidden], +#panel-content[hidden] { + display: none; +} diff --git a/src/terminal.ts b/src/terminal.ts index b5a8aa2..1b14038 100644 --- a/src/terminal.ts +++ b/src/terminal.ts @@ -2,6 +2,9 @@ import { Terminal } from "@xterm/xterm"; import { FitAddon } from "@xterm/addon-fit"; import { WebglAddon } from "@xterm/addon-webgl"; import { LigaturesAddon } from "@xterm/addon-ligatures"; +// Fenster-Styles zuerst, damit die Kaskade der früheren -Reihenfolge +// entspricht (Fenster-CSS vor xterm/fonts). CSP: kein style-src unsafe-inline. +import "./terminal-window.css"; import "@xterm/xterm/css/xterm.css"; import "@fontsource/jetbrains-mono/400.css"; import "@fontsource/jetbrains-mono/500.css"; diff --git a/terminal.html b/terminal.html index f4e8b0b..2769f95 100644 --- a/terminal.html +++ b/terminal.html @@ -3,454 +3,6 @@ Terminal -