diff --git a/Druckmaterial/Carousing (Zechen und Feiern)_A5.pdf b/Druckmaterial/Carousing (Zechen und Feiern)_A5.pdf new file mode 100644 index 0000000..11402e9 Binary files /dev/null and b/Druckmaterial/Carousing (Zechen und Feiern)_A5.pdf differ diff --git a/Druckmaterial/Handbücher/a5_spielerhandbuch_kapitel_01_charaktererstellung.odt b/Druckmaterial/Handbücher/a5_spielerhandbuch_kapitel_01_charaktererstellung.odt index 798fa26..22347ba 100644 Binary files a/Druckmaterial/Handbücher/a5_spielerhandbuch_kapitel_01_charaktererstellung.odt and b/Druckmaterial/Handbücher/a5_spielerhandbuch_kapitel_01_charaktererstellung.odt differ diff --git a/Druckmaterial/autogen_Präsentation/Carousing.odt b/Druckmaterial/autogen_Präsentation/Carousing.odt new file mode 100644 index 0000000..209a7b4 Binary files /dev/null and b/Druckmaterial/autogen_Präsentation/Carousing.odt differ diff --git a/Druckmaterial/autogen_inbox/Carousing (Zechen und Feiern).odt b/Druckmaterial/autogen_inbox/Carousing (Zechen und Feiern).odt new file mode 100644 index 0000000..fca3d7d Binary files /dev/null and b/Druckmaterial/autogen_inbox/Carousing (Zechen und Feiern).odt differ diff --git a/RPG/.obsidian/appearance.json b/RPG/.obsidian/appearance.json index 8f4d4d3..a935b3e 100644 --- a/RPG/.obsidian/appearance.json +++ b/RPG/.obsidian/appearance.json @@ -1,5 +1,9 @@ { - "cssTheme": "ITS Theme", + "cssTheme": "QuestJournal", "nativeMenus": false, - "theme": "moonstone" + "theme": "moonstone", + "enabledCssSnippets": [ + "quest-journal-fontsize", + "quest-journal-kontrast" + ] } \ No newline at end of file diff --git a/RPG/.obsidian/plugins/manual-sorting/data.json b/RPG/.obsidian/plugins/manual-sorting/data.json index 7d5c3b7..1a798c1 100644 --- a/RPG/.obsidian/plugins/manual-sorting/data.json +++ b/RPG/.obsidian/plugins/manual-sorting/data.json @@ -2,6 +2,7 @@ "customOrder": { "/": { "children": [ + "2026-10-24.md", "1-Sessions", "2-Spieler", "3-Welt", @@ -28,6 +29,9 @@ }, "1-Sessions/generische Tabellen": { "children": [ + "1-Sessions/generische Tabellen/Harissa Indoor-Waldläufertraining.md", + "1-Sessions/generische Tabellen/Magier Bibliotheks-Events.md", + "1-Sessions/generische Tabellen/Terian Kleriker-Gebetswoche.md", "1-Sessions/generische Tabellen/Kreaturen", "1-Sessions/generische Tabellen/Random Domain Events", "1-Sessions/generische Tabellen/Shop Catalog_v2.0.2.pdf", @@ -52,6 +56,7 @@ }, "1-Sessions/Info Snippets": { "children": [ + "1-Sessions/Info Snippets/Notiz - Burn-Out System aktiviert.md", "1-Sessions/Info Snippets/Baphomet.md", "1-Sessions/Info Snippets/Definiere Schatz und Schatzkarte.md", "1-Sessions/Info Snippets/Der Kreuzritter Stadtstaat.md", @@ -137,6 +142,7 @@ }, "1-Sessions/Sitzungsarchiv/Sitzung 008 06.03.2026": { "children": [ + "1-Sessions/Sitzungsarchiv/Sitzung 008 06.03.2026/Unbenannt.md", "1-Sessions/Sitzungsarchiv/Sitzung 008 06.03.2026/Übersicht Prep 08.md", "1-Sessions/Sitzungsarchiv/Sitzung 008 06.03.2026/Garana Events.md", "1-Sessions/Sitzungsarchiv/Sitzung 008 06.03.2026/Hooks.md" @@ -185,6 +191,7 @@ }, "3-Welt": { "children": [ + "3-Welt/Weltstatus & Offene Enden.md", "3-Welt/Wetter", "3-Welt/Geheimnisse", "3-Welt/Königreich Taloria" @@ -452,6 +459,9 @@ }, "5-Regeln/Hausregeln": { "children": [ + "5-Regeln/Hausregeln/Carousing (Zechen und Feiern).md", + "5-Regeln/Hausregeln/Erwerb und Abschreiben von Zaubern.md", + "5-Regeln/Hausregeln/Wochen- und Rastaktivitäten.md", "5-Regeln/Hausregeln/Fertigkeit_Kochen.md", "5-Regeln/Hausregeln/Westreich D&D Hausregeln V1.1.pdf" ], @@ -495,6 +505,7 @@ }, "7-Prep": { "children": [ + "7-Prep/Markdown zu A5 exportieren.md", "7-Prep/Abenteuer", "7-Prep/Bücher", "7-Prep/Ereignisse", @@ -568,6 +579,7 @@ }, "zz_archiv/images": { "children": [ + "zz_archiv/images/carouse-1.jpg", "zz_archiv/images/Westreiche.jpeg", "zz_archiv/images/Gharana_Umgebung.jpeg", "zz_archiv/images/Radomandeus.jpeg", diff --git a/RPG/.obsidian/snippets/quest-journal-fontsize.css b/RPG/.obsidian/snippets/quest-journal-fontsize.css new file mode 100644 index 0000000..881f8f1 --- /dev/null +++ b/RPG/.obsidian/snippets/quest-journal-fontsize.css @@ -0,0 +1,17 @@ +/* ========================================================================== + Quest Journal – größere Grundschrift + Wert (20px) nach Belieben anpassen (z. B. 18px oder 22px). + ========================================================================== */ +.markdown-source-view, +.markdown-preview-view { + font-size: 20px !important; +} + +/* ========================================================================== + Dokumentenbaum (Datei-Explorer) – größere Schrift + Wert (18px) nach Belieben anpassen. + ========================================================================== */ +.nav-file-title, +.nav-folder-title { + font-size: 18px !important; +} diff --git a/RPG/.obsidian/snippets/quest-journal-kontrast.css b/RPG/.obsidian/snippets/quest-journal-kontrast.css new file mode 100644 index 0000000..7c2dd6b --- /dev/null +++ b/RPG/.obsidian/snippets/quest-journal-kontrast.css @@ -0,0 +1,11 @@ +/* ========================================================================== + Quest Journal – besserer Kontrast im Dunkelmodus („Ancient Leather“) + Deutlich hellerer Text auf dunkelbraunem Grund. + Werte nach Belieben anpassen. + ========================================================================== */ +body.theme-dark { + --text-normal: #efe7d3; /* Grundtext: fast weiß, deutlich heller */ + --text-muted: #c4b69e; /* abgeschwächter Text (Metadata, Links …) */ + --text-faint: #9c8f79; /* dezentester Text */ + --text-navbar: #c4b69e; /* Datei-Explorer (Dokumentenbaum) */ +} diff --git a/RPG/.obsidian/themes/QuestJournal/manifest.json b/RPG/.obsidian/themes/QuestJournal/manifest.json new file mode 100644 index 0000000..bba921e --- /dev/null +++ b/RPG/.obsidian/themes/QuestJournal/manifest.json @@ -0,0 +1,9 @@ +{ + "name": "Quest Journal", + "version": "1.0.0", + "minAppVersion": "1.0.0", + "author": "Jack Lockwood", + "authorUrl": "", + "fundingUrl": "", + "isDesktopOnly": false +} diff --git a/RPG/.obsidian/themes/QuestJournal/theme.css b/RPG/.obsidian/themes/QuestJournal/theme.css new file mode 100644 index 0000000..d9b0b41 --- /dev/null +++ b/RPG/.obsidian/themes/QuestJournal/theme.css @@ -0,0 +1,523 @@ +/* @settings +name: Quest Journal Settings +id: quest-journal-settings +settings: + - + id: info-text-quest-journal + type: info-text + title: "Quest Journal Theme" + description: "A fantasy RPG inspired theme for Obsidian." + markdown: true + - + title: Typography + id: qj-typography + type: heading + level: 1 + - + title: Header Font + id: qj-header-font + type: variable-text + default: "'Cinzel', 'Crimson Text', serif" + description: "Font family for headers (H1-H6)." + - + title: Body Font + id: qj-body-font + type: variable-text + default: "'Crimson Text', 'Georgia', serif" + description: "Font family for main text." + - + title: Appearance + id: qj-appearance + type: heading + level: 1 + - + title: Hide Paper Texture + id: qj-hide-texture + type: class-toggle + description: "Removes the subtle lined paper background texture." + - + title: Header Underlines + id: qj-header-underlines + type: class-select + default: qj-header-underline-none + options: + - + label: Solid Line + value: qj-header-underline-solid + - + label: Double Line + value: qj-header-underline-double + - + label: Dotted Line + value: qj-header-underline-dotted + - + label: None + value: qj-header-underline-none + - + title: Colors (Light Mode) + id: qj-colors-light + type: heading + level: 2 + - + title: Parchment Background + id: background-primary-light + type: variable-themed-color + format: hex + default-light: '#f0e6d2' + - + title: Ink Color + id: text-normal-light + type: variable-themed-color + format: hex + default-light: '#2b221b' + - + title: Accent Color (Wax Red) + id: text-accent-light + type: variable-themed-color + format: hex + default-light: '#8a3a3a' + - + title: Colors (Dark Mode) + id: qj-colors-dark + type: heading + level: 2 + - + title: Leather Background + id: background-primary-dark + type: variable-themed-color + format: hex + default-dark: '#1e1915' + - + title: Gold Text + id: text-normal-dark + type: variable-themed-color + format: hex + default-dark: '#dcd0b8' + - + title: Accent Color (Magic Blue) + id: text-accent-dark + type: variable-themed-color + format: hex + default-dark: '#7ca8cf' +*/ + +/* ========================================================================== + THEME: QUEST JOURNAL + STYLE: Parchment (Light) / Ancient Leather (Dark) + BASE: Tech001 Structure + ========================================================================== */ + +/* Import a classic serif font for that old-world feel */ +@import url('https://fonts.googleapis.com/css2?family=Crimson+Text:ital,wght@0,400;0,600;0,700;1,400&family=Cinzel:wght@400;700&display=swap'); + +/* ========================================================================== + 1. VARIABLES & PALETTE + ========================================================================== */ + +body { + --nav-indentation-guide-color: var(--text-faint) !important; + --nav-indentation-guide-width: 1px !important; + + /* Typography - Default fallback if settings fail */ + --font-interface: 'Crimson Text', 'Georgia', serif; + --font-text: 'Crimson Text', 'Georgia', serif; + --font-family-code: 'Consolas', 'Menlo', monospace; + --font-headers: 'Cinzel', 'Crimson Text', serif; + + /* Shapes - Slightly softer edges */ + --radius-s: 2px; + --radius-m: 4px; + --radius-l: 8px; + + --h1-size: 2.4em; + --h2-size: 1.8em; + --h3-size: 1.4em; + --code-size: 0.9em; +} + +/* Settings: Typography Overrides */ +body { + --font-headers: var(--qj-header-font, 'Cinzel', 'Crimson Text', serif); + --font-text: var(--qj-body-font, 'Crimson Text', 'Georgia', serif); +} + +/* --- DARK THEME (ANCIENT LEATHER) --- */ +body.theme-dark { + /* Backgrounds: Dark brown leather tones */ + --background-primary: #1e1915; + --background-secondary: #251f1a; + --background-secondary-alt: #16120f; + --background-modifier-border: #3e3226; + --background-blockquote: #2a221d; + + /* Text: Faded gold and old paper */ + --text-normal: #dcd0b8; + --text-muted: #8c8175; + --text-faint: #5a5148; + --text-navbar: #8c8175; + --text-bold: #e8ded0; + + /* Headers: Gold/Brass */ + --h1-color: #cdb278; + --h2-color: #cdb278; + --h3-color: #bfa367; + --h4-color: #bfa367; + --h5-color: #bfa367; + --h6-color: #bfa367; + + /* Accents: Muted Magic Blue/Purple */ + --text-accent: #7ca8cf; + --text-accent-hover: #9ec1e0; + --interactive-accent: #3b2e25; + --caret-color: #cdb278; + + /* Code */ + --code-background: #15110e; + --code-border-color: #3e3226; + --code-normal: #dcd0b8; + --code-comment: #5a5148; + --code-string: #c17e73; /* Muted Red */ + --code-function: #cdb278; /* Gold */ + --code-keyword: #7ca8cf; /* Blue */ + --code-operator: #8c8175; + --code-property: #8fb58e; /* Muted Green */ + --code-value: #d4a768; + + /* UI Specific */ + --scrollbar-thumb: #3e3226; + --tab-hover: rgba(205, 178, 120, 0.05); + --sidebar-hover: rgba(205, 178, 120, 0.1); +} + +/* Settings: Dark Mode Colors Override */ +body.theme-dark { + --background-primary: var(--background-primary-dark, #1e1915); + --text-normal: var(--text-normal-dark, #dcd0b8); + --text-accent: var(--text-accent-dark, #7ca8cf); +} + +/* --- LIGHT THEME (QUEST PARCHMENT) --- */ +body.theme-light { + /* Backgrounds: Warm Paper */ + --background-primary: #f0e6d2; + --background-secondary: #e6dac1; + --background-secondary-alt: #f7f1e3; + --background-modifier-border: #c9bca6; + --background-blockquote: #e8dcc5; + + /* Text: Dark Ink */ + --text-normal: #2b221b; + --text-muted: #6b5a4b; + --text-faint: #a69686; + --text-navbar: #6b5a4b; + --text-bold: #1a1410; + + /* Headers: Sealing Wax Red / Deep Ink */ + --h1-color: #8a3a3a; + --h2-color: #2b221b; + --h3-color: #4a3c31; + --h4-color: #4a3c31; + --h5-color: #4a3c31; + --h6-color: #4a3c31; + + /* Accents: Ink Blue / Rustic Gold */ + --text-accent: #8a3a3a; /* Rust Red links */ + --text-accent-hover: #a84b4b; + --interactive-accent: #dcd0b8; + --caret-color: #8a3a3a; + + /* Code */ + --code-background: #e9e1d1; + --code-border-color: #c9bca6; + --code-normal: #2b221b; + --code-comment: #8c8175; + --code-string: #a04040; + --code-function: #2b5c85; + --code-keyword: #5c3a75; + --code-operator: #6b5a4b; + --code-property: #3a6b3d; + --code-value: #9c6b1f; + + /* UI Specific */ + --scrollbar-thumb: #c9bca6; + --tab-hover: rgba(138, 58, 58, 0.05); + --sidebar-hover: rgba(138, 58, 58, 0.08); +} + +/* Settings: Light Mode Colors Override */ +body.theme-light { + --background-primary: var(--background-primary-light, #f0e6d2); + --text-normal: var(--text-normal-light, #2b221b); + --text-accent: var(--text-accent-light, #8a3a3a); +} + +/* ========================================================================== + 2. GLOBAL LAYOUT & TYPOGRAPHY + ========================================================================== */ + +.markdown-source-view, +.markdown-preview-view { + font-family: var(--font-text); + line-height: 1.8; /* Slightly looser line height for journal feel */ + font-size: 17px; + color: var(--text-normal); + background-image: linear-gradient(rgba(0,0,0,0.02) 1px, transparent 1px); + background-size: 100% 2em; /* Subtle lined paper effect */ +} + +/* Settings: Hide Texture */ +body.qj-hide-texture .markdown-source-view, +body.qj-hide-texture .markdown-preview-view { + background-image: none; +} + +/* --- TEXT HIERARCHY --- */ +.cm-header, h1, h2, h3, h4, h5, h6 { + color: var(--h1-color) !important; + font-family: var(--font-headers) !important; + font-variant: small-caps; + letter-spacing: 0.05em; + padding-bottom: 0px; + margin-bottom: 0.7em !important; + margin-top: 1.5em !important; +} + +/* Settings: Header Underline Styles */ +body.qj-header-underline-solid .cm-header, +body.qj-header-underline-solid h1, +body.qj-header-underline-solid h2, +body.qj-header-underline-solid h3 { + border-bottom-style: solid; + border-bottom-height: 0.05px; +} + +body.qj-header-underline-double .cm-header, +body.qj-header-underline-double h1, +body.qj-header-underline-double h2, +body.qj-header-underline-double h3 { + border-bottom-style: double; + border-bottom-width: 3px; +} + +body.qj-header-underline-dotted .cm-header, +body.qj-header-underline-dotted h1, +body.qj-header-underline-dotted h2, +body.qj-header-underline-dotted h3 { + border-bottom-style: dotted; + border-bottom-width: 2px; +} + +body.qj-header-underline-none .cm-header, +body.qj-header-underline-none h1, +body.qj-header-underline-none h2, +body.qj-header-underline-none h3 { + border-bottom: none; +} + +h1 { text-align: center; border-bottom: 2px solid var(--text-accent); } + +.cm-line, p, li, ul, ol { + color: var(--text-normal) !important; +} + +strong, b, .cm-strong { + color: var(--text-bold) !important; + font-weight: 700; +} + +/* Minimalist Scrollbars (Adapted to look rustic) */ +::-webkit-scrollbar { + width: 12px; height: 12px; background: transparent; +} +::-webkit-scrollbar-thumb { + background: var(--scrollbar-thumb); + border-radius: 2px; + border: 2px solid var(--background-primary); +} +::-webkit-scrollbar-thumb:hover { + background: var(--text-muted); +} + +/* ========================================================================== + 3. CENTERED LAYOUT (Retained from Tech001) + ========================================================================== */ + +.markdown-source-view.mod-cm6 .cm-scroller, +.markdown-preview-view { + padding-top: 50px !important; +} + +.markdown-source-view.mod-cm6:not(.is-readable-line-width) .cm-sizer, +.markdown-preview-view:not(.is-readable-line-width) .markdown-preview-sizer { + max-width: 1800px !important; /* Slightly narrower for reading comfort */ + width: 100% !important; + margin-left: auto !important; + margin-right: auto !important; + margin-inline: auto !important; + padding-left: 40px !important; + padding-right: 40px !important; + box-sizing: border-box !important; + /* Paper Texture Shadow */ + box-shadow: 0 0 50px -10px rgba(0,0,0,0.1); + background-color: var(--background-primary); +} + +/* ========================================================================== + 4. UI ELEMENTS + ========================================================================== */ + +.titlebar { background-color: transparent !important; z-index: 0; } + +.titlebar-button-container { + background-color: var(--background-secondary) !important; +} + +/* Tabs like bookmarks */ +.workspace-tab-header-container { + background-color: var(--background-secondary) !important; + border-bottom: 2px solid var(--background-modifier-border); + padding-top: 5px; +} + +.workspace-tab-header { + background-color: var(--background-secondary-alt) !important; + color: var(--text-muted); + border: 1px solid var(--background-modifier-border); + border-bottom: none; + border-radius: 6px 6px 0 0; + margin-right: 2px; + font-family: var(--font-headers); + font-size: 0.9em; +} + +.workspace-tab-header.is-active { + background-color: var(--background-primary) !important; + color: var(--text-accent); + font-weight: bold; + border-top: 2px solid var(--text-accent); + padding-bottom: 2px; +} + +/* Sidebar */ +.nav-folder-title, .nav-file-title { + font-family: var(--font-interface); + font-size: 1em; + color: var(--text-navbar); + border-radius: var(--radius-m); + padding: 6px 12px; +} + +.nav-file-title.is-active { + color: var(--text-normal) !important; + background-color: var(--sidebar-hover); + border-left: 3px solid var(--text-accent); +} + +/* ========================================================================== + 5. EDITOR STYLES (Journal Specific) + ========================================================================== */ + +/* Blockquotes - Scroll Style */ +blockquote { + border: 1px solid var(--background-modifier-border); + border-left: 4px solid var(--text-accent); + background-color: var(--background-blockquote); + border-radius: 2px; + padding: 16px 24px; + margin: 1.5em 0; + color: var(--text-normal); + font-style: italic; + font-family: var(--font-interface); + position: relative; + box-shadow: 2px 2px 5px rgba(0,0,0,0.05); +} + +/* Checkboxes - Ink Squares */ +input[type=checkbox] { + -webkit-appearance: none; appearance: none; + border-radius: 2px; + border: 1.5px solid var(--text-muted); + width: 16px; height: 16px; + position: relative; top: 3px; + cursor: pointer; + background-color: transparent; +} +input[type=checkbox]:checked { + background-color: transparent; + border-color: var(--text-accent); +} +input[type=checkbox]:checked:after { + content: 'x'; + color: var(--text-accent); + position: absolute; + top: -4px; left: 2px; + font-size: 16px; + font-family: cursive; + font-weight: bold; +} + +/* Horizontal Rules - Ornamental */ +hr { + border: none; + height: 1px; + background-image: linear-gradient(to right, transparent, var(--text-muted), transparent); + margin: 3em 0; +} + +/* ========================================================================== + 6. CODE BLOCKS + ========================================================================== */ + +.markdown-reading-view code, +.markdown-source-view.is-live-preview .cm-inline-code:not(.cm-formatting) { + color: var(--text-normal) !important; + background-color: var(--background-secondary) !important; + border: 1px solid var(--background-modifier-border); + border-radius: 2px; + padding: 2px 6px; + font-family: var(--font-family-code); + font-size: 0.85em !important; + box-shadow: inset 1px 1px 3px rgba(0,0,0,0.05); +} + +/* Code Blocks Container */ +.markdown-reading-view pre, +.markdown-source-view.is-live-preview .HyperMD-codeblock { + background-color: var(--code-background); + border: 1px dashed var(--background-modifier-border); + border-radius: 2px; + font-family: var(--font-family-code); + line-height: 1.5 !important; +} + +.markdown-source-view.is-live-preview .HyperMD-codeblock-begin, +.markdown-source-view.is-live-preview .HyperMD-codeblock-end { + border: none; + background-color: var(--code-background); + color: var(--text-faint); + opacity: 0.7; +} + +/* ========================================================================== + 7. CUSTOM ICONS (Ink Dots) + ========================================================================== */ + +.nav-folder-title-content, +.nav-file-title-content { + display: flex !important; + align-items: center; + gap: 6px !important; +} + +/* Simple ink dot for files */ +body:not(.remove-file-icons) .nav-file-title .nav-file-title-content:not(.mk-tree-text)::before { + content: "•"; + color: var(--text-muted); + font-size: 1.5em; + line-height: 0.5em; + flex-shrink: 0; +} + +.nav-file-title.is-active .nav-file-title-content::before { + color: var(--text-accent); +} \ No newline at end of file diff --git a/RPG/5-Regeln/Hausregeln/Carousing (Zechen und Feiern).md b/RPG/5-Regeln/Hausregeln/Carousing (Zechen und Feiern).md index 1c6d82c..a3749fa 100644 --- a/RPG/5-Regeln/Hausregeln/Carousing (Zechen und Feiern).md +++ b/RPG/5-Regeln/Hausregeln/Carousing (Zechen und Feiern).md @@ -1,3 +1,5 @@ +![[carouse-1.jpg|255]] + # Hausregel: Carousing (Zechen & Feiern für Erfahrungspunkte) > **Zweck:** In OSR-Spielen (und passend zu Kämpfern wie Rain) dient Gold oft als direkte Quelle für Erfahrungspunkte (XP) – allerdings nicht, indem es im Beutel versauert, sondern indem es ausgegeben wird! *Carousing* (Zechen, Feiern, Wetten und Großzügigkeit in Tavernen) belohnt das Verprassen von Schätzen mit XP, birgt aber auch typische Abenteuer-Kater-Risiken. diff --git a/RPG/7-Prep/Markdown zu A5 exportieren.md b/RPG/7-Prep/Markdown zu A5 exportieren.md new file mode 100644 index 0000000..e7a5bd5 --- /dev/null +++ b/RPG/7-Prep/Markdown zu A5 exportieren.md @@ -0,0 +1,100 @@ +# Markdown zu A5 exportieren (LibreOffice ODT) + +Aus den Markdown-Notizen dieser Knowledgebase lassen sich **editierbare A5-Dokumente** +für LibreOffice Writer erzeugen, die dort manuell nachbearbeitet werden können. + +Alle Befehle werden aus dem Repo-Wurzelverzeichnis ausgeführt (dort, wo `tools/`, `RPG/` +und `Druckmaterial/` liegen). + +## Arbeitsablauf + +1. **Generieren** – das Skript erzeugt ein ODT nach `Druckmaterial/autogen_inbox/`. +2. **Bearbeiten** – das ODT in LibreOffice Writer öffnen und anpassen. +3. **Sichern** – nachbearbeitete Dokumente manuell nach `Druckmaterial/autogen_Präsentation/` + verschieben (dort sind sie vor erneuter Generierung sicher). +4. **PDF-Export** – bei Bedarf manuell in LibreOffice (`Datei → Exportieren als PDF`). + +`autogen_inbox/` darf jederzeit überschrieben werden; `autogen_Präsentation/` enthält nur +die nachbearbeiteten Dokumente. + +--- + +## Befehl + +```bash +./tools/md2odt.sh "RPG/5-Regeln/Hausregeln/Carousing (Zechen und Feiern).md" +``` + +→ Ausgabe: `Druckmaterial/autogen_inbox/.odt` + +**Optionaler zweiter Parameter** setzt einen eigenen Ausgabenamen: + +```bash +./tools/md2odt.sh "RPG/…/datei.md" "Mein_Name" +``` + +--- + +## Was automatisch behandelt wird (Obsidian-Syntax) + +- `[[Bild.jpg|375]]` → eingebettetes Bild, Breite 375 px (wird in cm umgerechnet) +- `[[Bild.jpg]]` → eingebettetes Bild in voller Textbreite +- `[[Notizname]]` → Klartext (der Notizname) +- `👉` → `→` und `🟡` → `●` (drucktaugliche Glyphen) +- `☀` und `⚠` → bleiben erhalten (LibreOffice setzt automatisch eine Fallback-Schrift ein) +- dekorative Emojis (`🌸`, `🗺`, …) → werden entfernt (der Text dahinter trägt die Bedeutung) +- `==Markierung==` → fett +- `%%Kommentar%%` → entfernt +- Pipe-Tabellen → echte Writer-Tabellen, Spaltenbreiten automatisch proportional zum Inhalt +- YAML-Frontmatter → wird von Pandoc als Metadaten genutzt + +Bilder werden unabhängig vom Arbeitsverzeichnis über absolute Pfade gefunden. +Die Überschriften bleiben echte Stile („Überschrift 1/2/…“), sodass sie sich über +`F11` (Formatvorlagen) global anpassen lassen. + +--- + +## Layout anpassen + +Das A5-Layout (Seitenmaß, Ränder, Schriften, Schriftgröße) steckt in +`tools/make_reference_odt.py`. Nach einer Änderung dort: + +```bash +python3 tools/make_reference_odt.py +``` + +Das schreibt `tools/a5-reference.odt` neu. Danach erzeugte ODTs nutzen das neue Layout. + +Aktuelle Werte: + +| Was | Wo in `tools/make_reference_odt.py` | +|---|---| +| **Seitenmaß** | `fo:page-width/height` (14,801 × 21,001 cm = A5) | +| **Ränder** | `fo:margin-top/bottom/left/right` (0,8 / 1,0 / 1,0 / 0,7 cm) | +| **Grundschrift** | `"Times New Roman"` → `"Alegreya"` | +| **Überschriften** | `"Arial"` → `"Cinzel"` | +| **Schriftgröße** | `fo:font-size="12pt"` → `"10pt"` | +| **Seitennummern** | Footer im Master-Page (aktuell entfernt) | + +--- + +## Dateien der Werkzeugkette (in `tools/`) + +| Datei | Zweck | +|---|---| +| `md2odt.sh` | Markdown → A5-ODT (nach `autogen_inbox/`) | +| `obsidian_preprocess.py` | Obsidian-Syntax (Wikilinks, Emojis, `==…==`, `%%…%%`) → sauberes Markdown | +| `autowidth.lua` | Tabellen-Spaltenbreiten proportional zum Inhalt | +| `a5-reference.odt` | ODT-Vorlage (Stile, A5-Layout) | +| `make_reference_odt.py` | erzeugt `a5-reference.odt` neu | + +--- + +## Einrichtung (einmalig, bereits erledigt) + +Damit der Befehl läuft, ist Folgendes installiert: + +- **Pandoc** 3.12 (`~/bin/pandoc`) +- **Alegreya** (Grundschrift) und **Cinzel** (Überschriften) unter `~/.local/share/fonts/` + +Auf einem neuen Rechner müssten diese Komponenten entsprechend nachinstalliert werden. diff --git a/RPG/zz_archiv/images/carouse-1.jpg b/RPG/zz_archiv/images/carouse-1.jpg new file mode 100644 index 0000000..bc0b433 Binary files /dev/null and b/RPG/zz_archiv/images/carouse-1.jpg differ diff --git a/tools/a5-reference.odt b/tools/a5-reference.odt new file mode 100644 index 0000000..409cf76 Binary files /dev/null and b/tools/a5-reference.odt differ diff --git a/tools/autowidth.lua b/tools/autowidth.lua new file mode 100644 index 0000000..eac4e58 --- /dev/null +++ b/tools/autowidth.lua @@ -0,0 +1,58 @@ +-- Verteilt Tabellenspalten proportional zur Inhaltslänge (statt gleicher +-- Breiten aus der Markdown-Trennzeile). Für Tabellen mit langer +-- Beschreibungsspalte (typisch bei RPG-Tabellen) deutlich besser lesbar. +-- +-- Die Breite einer Spalte = max. Zeichenlänge ihrer Zellen (Header + Rumpf), +-- normalisiert auf Anteile. Mindestbreite 12 %, um schmale Kennspalten +-- (z. B. "d6") nicht zu erdrücken. + +local FLOOR = 0.08 + +local function strlen(s) + local ok, n = pcall(utf8.len, s) + if ok then return n end + return #s +end + +local function celltext(blocks) + return pandoc.utils.stringify(blocks) +end + +function Table(tbl) + local ncols = #tbl.colspecs + if ncols < 1 then return tbl end + + local lens = {} + for i = 1, ncols do lens[i] = 1 end + + local function measure(cells) + for i, cell in ipairs(cells) do + local l = strlen(celltext(cell.contents)) + if l > lens[i] then lens[i] = l end + end + end + + if tbl.head and tbl.head.rows then + for _, row in ipairs(tbl.head.rows) do measure(row.cells) end + end + for _, body in ipairs(tbl.bodies) do + for _, row in ipairs(body.body) do measure(row.cells) end + end + + local total = 0 + for i = 1, ncols do + lens[i] = math.sqrt(lens[i]) + total = total + lens[i] + end + + if total > 0 then + for i = 1, ncols do + local w = lens[i] / total + if w < FLOOR then w = FLOOR end + -- ColSpec ist positionsbasiert: [1]=align, [2]=width + tbl.colspecs[i][2] = w + end + end + + return tbl +end diff --git a/tools/make_reference_odt.py b/tools/make_reference_odt.py new file mode 100755 index 0000000..869a83b --- /dev/null +++ b/tools/make_reference_odt.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +""" +Erzeugt tools/a5-reference.odt aus der Pandoc-Standardreferenz, +angepasst an dein A5-Layout: + + - A5 (14,801 x 21,001 cm), Ränder oben 0,8 / unten 1,0 / links 1,0 / rechts 0,7 cm + - Grundschrift Alegreya 10 pt, Überschriften Cinzel + - keine Seitennummern (Footer entfernt) + +Aufruf: python3 make_reference_odt.py +""" +import io +import os +import re +import subprocess +import zipfile + +TOOLS = os.path.dirname(os.path.abspath(__file__)) +OUT = os.path.join(TOOLS, "a5-reference.odt") + +# 1) Pandoc-Standardreferenz holen +default = subprocess.check_output( + ["pandoc", "--print-default-data-file", "reference.odt"] +) + +zin = zipfile.ZipFile(io.BytesIO(default)) +names = zin.namelist() +items = {n: zin.read(n) for n in names} + +styles = items["styles.xml"].decode("utf-8") + +# 2) Gezielte Ersetzungen +REPL = [ + # --- Seite A5 + Ränder --- + ('fo:page-width="8.5in"', 'fo:page-width="14.801cm"'), + ('fo:page-height="11in"', 'fo:page-height="21.001cm"'), + ('fo:margin-top="1in"', 'fo:margin-top="0.8cm"'), + ('fo:margin-bottom="1in"', 'fo:margin-bottom="1cm"'), + ('fo:margin-left="1in"', 'fo:margin-left="1cm"'), + ('fo:margin-right="1in"', 'fo:margin-right="0.7cm"'), + # --- Schriften --- + ("Times New Roman", "Alegreya"), + ("Arial", "Cinzel"), + ("Lucida Sans Unicode", "Cinzel"), + ("Tahoma1", "Cinzel"), + ("Tahoma", "Cinzel"), + # --- Grundschrift 12 pt -> 10 pt --- + ('fo:font-size="12pt"', 'fo:font-size="10pt"'), + ('font-size-asian="12pt"', 'font-size-asian="10pt"'), + ('font-size-complex="12pt"', 'font-size-complex="10pt"'), +] + +for a, b in REPL: + styles = styles.replace(a, b) + +# 3) Footer (Seitennummer) aus dem Master-Page entfernen +styles = re.sub(r".*?", "", styles, flags=re.S) + +items["styles.xml"] = styles.encode("utf-8") + +# 4) Neu packen: mimetype zuerst und unkomprimiert +with zipfile.ZipFile(OUT, "w") as z: + z.writestr("mimetype", items["mimetype"], compress_type=zipfile.ZIP_STORED) + for n in names: + if n == "mimetype": + continue + z.writestr(n, items[n], compress_type=zipfile.ZIP_DEFLATED) + +print("OK:", OUT) diff --git a/tools/md2odt.sh b/tools/md2odt.sh new file mode 100755 index 0000000..3e2ba59 --- /dev/null +++ b/tools/md2odt.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# +# Markdown (Obsidian) -> editierbares LibreOffice-ODT (A5) +# +# Aufruf: +# ./tools/md2odt.sh [ausgabename-ohne-endung] +# +# Ausgabe (Standard): Druckmaterial/.odt +# +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +VAULT="$ROOT/RPG" +TOOLS="$ROOT/tools" +OUTDIR="${OUTDIR:-$ROOT/Druckmaterial/autogen_inbox}" + +if [ "$#" -lt 1 ]; then + echo "Aufruf: $0 [ausgabename]" >&2 + exit 1 +fi + +SRC="$(realpath "$1")" +NAME="${2:-$(basename "$SRC" .md)}" +OUT="$OUTDIR/${NAME}.odt" + +mkdir -p "$OUTDIR" + +TMP="$(mktemp -d)" +trap 'rm -rf "$TMP"' EXIT + +# 1) Obsidian-Syntax vorverarbeiten +python3 "$TOOLS/obsidian_preprocess.py" "$VAULT" < "$SRC" > "$TMP/in.md" + +# 2) Markdown -> ODT (A5-Referenzvorlage; H1 bleibt als "Heading 1" erhalten) +pandoc "$TMP/in.md" \ + -f markdown+raw_html \ + -t odt \ + --reference-doc="$TOOLS/a5-reference.odt" \ + --lua-filter="$TOOLS/autowidth.lua" \ + -o "$OUT" + +echo "OK: $OUT" diff --git a/tools/obsidian_preprocess.py b/tools/obsidian_preprocess.py new file mode 100644 index 0000000..4c57cf4 --- /dev/null +++ b/tools/obsidian_preprocess.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +""" +Vorverarbeitung von Obsidian-Markdown zu sauberem Pandoc-Markdown. + +Behandelt: + - Obsidian-Wikilinks: [[Ziel]] [[Ziel|Anzeige]] [[bild.jpg|BreitePx]] + - Emoji -> drucktaugliche Glyphen bzw. Text (dekorative Emojis werden entfernt) + - ==Markierung== -> **fett** (drucktauglicher Ersatz) + - %% Kommentare %% -> entfernt + - Variation-Selektoren (U+FE0F/U+FE0E) entfernen + +Aufruf: + obsidian_preprocess.py < eingabe.md > ausgabe.md +""" +import os +import re +import sys + +IMG_EXT = {".jpg", ".jpeg", ".png", ".webp", ".gif", ".bmp", ".svg", ".avif"} + +# Emoji -> Ersatz (leerer String = entfernen) +EMOJI = { + "\U0001F449": "\u2192", # 👉 -> + "\U0001F7E1": "\u25CF", # 🟡 ● + "\u26A0": "\u26A0", # ⚠ (wird über DejaVu-Fallback gesetzt) + "\u2600": "\u2600", # ☀ (DejaVu-Fallback) + "\U0001F338": "", # 🌸 + "\U0001F342": "", # 🍂 + "\u2744": "", # ❄ + "\U0001F324": "", # 🌤 + "\U0001F5FA": "", # 🗺 + "\U0001F3D4": "", # 🏔 + "\U0001F5E3": "", # 🗣 + "\U0001F48E": "", # 💎 + "\U0001F3B2": "", # 🎲 + "\u26A1": "", # ⚡ + "\U0001F4C8": "", # 📈 + "\U0001F4C9": "", # 📉 + "\U0001F504": "", # 🔄 +} +VS = {"\uFE0F", "\uFE0E"} + +SKIP_DIRS = {".git", ".obsidian", ".trash", "node_modules"} + + +def scan_images(root: str) -> dict: + """basename(lower) -> absoluter Pfad (nur Nicht-.trash-Pfade).""" + mapping = {} + + def walk(): + for dirpath, dirnames, filenames in os.walk(root): + dirnames[:] = [d for d in dirnames if d not in SKIP_DIRS] + for fn in filenames: + if os.path.splitext(fn)[1].lower() in IMG_EXT: + # Absoluter Pfad, damit Pandoc das Bild unabhängig vom + # aktuellen Arbeitsverzeichnis findet. + full = os.path.abspath(os.path.join(dirpath, fn)) + key = fn.lower() + mapping.setdefault(key, full) + walk() + return mapping + + +def px_to_cm(px: float) -> float: + return round(px / 96.0 * 2.54, 2) + + +def resolve_wikilink(image_map: dict, inner: str) -> str: + if "|" in inner: + target, disp = inner.split("|", 1) + else: + target, disp = inner, None + target = target.strip() + ext = os.path.splitext(target.lower())[1] + if ext in IMG_EXT: + path = image_map.get(target.lower(), target) + alt = os.path.basename(target) + if disp is not None and disp.strip().isdigit(): + width = px_to_cm(int(disp.strip())) + return f"![{alt}]({path}){{width={width}cm}}" + return f"![{alt}]({path}){{width=100%}}" + # Notiz-Link -> Klartext + return (disp.strip() if disp is not None else target) + + +def process(text: str, image_map: dict) -> str: + # 1. Kommentare + text = re.sub(r"%%.*?%%", "", text, flags=re.DOTALL) + # 2. Wikilinks + text = re.sub(r"\[\[([^\]]+)\]\]", lambda m: resolve_wikilink(image_map, m.group(1)), text) + # 3. Variation-Selektoren + for vs in VS: + text = text.replace(vs, "") + # 4. Emoji + for k, v in EMOJI.items(): + text = text.replace(k, v) + # 5. ==mark== -> **fett** + text = re.sub(r"==([^=\n]+)==", r"**\1**", text) + # 6. Leerraum glätten (nach Emoji-Entfernung), aber Tabellen/Code unberührt + out = [] + for line in text.split("\n"): + stripped = line.lstrip() + if not stripped.startswith("|") and not stripped.startswith("```"): + line = re.sub(r"[ \t]{2,}", " ", line) + out.append(line) + return "\n".join(out) + + +def main(): + root = sys.argv[1] if len(sys.argv) > 1 else "." + image_map = scan_images(root) + sys.stdout.write(process(sys.stdin.read(), image_map)) + + +if __name__ == "__main__": + main()