str docs
This commit is contained in:
parent
1b55b603fe
commit
c49a59f46c
11 changed files with 5676 additions and 1433 deletions
Binary file not shown.
1230
mandates/bwt/script-poweron.html
Normal file
1230
mandates/bwt/script-poweron.html
Normal file
File diff suppressed because it is too large
Load diff
1230
mandates/bwt/script.html
Normal file
1230
mandates/bwt/script.html
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -62,30 +62,30 @@ BWT (Best Water Technology) ist Europas führendes Wastertechnologie-Unternehmen
|
|||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ AI SUPPORT SYSTEM │
|
||||
│ AI SUPPORT SYSTEM │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Telefon │────▶│ AI Voice │────▶│ Backend │ │
|
||||
│ │ Interface │ │ Assistant │ │ Services │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Telefon │───> │ AI Voice │────>│ Backend │ │
|
||||
│ │ Interface │ │ Assistant │ │ Services │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
│ │ │ │
|
||||
│ ▼ ▼ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Triage & │ │ Database │ │
|
||||
│ │ Routing │ │ (CRM) │ │
|
||||
│ └──────────────┘ └──────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────┐ ▼ │
|
||||
│ │ Agent UI │◀────────────┤ │
|
||||
│ │ Dashboard │ │
|
||||
│ └──────────────┘ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Triage & │ │ Database │ │
|
||||
│ │ Routing │ │ (CRM) │ │
|
||||
│ └──────────────┘ └──────────────┘ │
|
||||
│ | | │
|
||||
│ ┌──────────────┐ | │
|
||||
│ │ Agent UI │<──────────── │
|
||||
│ │ Dashboard │ │
|
||||
│ └──────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌──────────────┐ │
|
||||
│ │ Email │ │
|
||||
│ │ Service │ │
|
||||
│ └──────────────┘ │
|
||||
│ ┌──────────────┐ │
|
||||
│ │ Email │ │
|
||||
│ │ Service │ │
|
||||
│ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
|
|
|
|||
BIN
poweron/strategy/PowerOn Playground - Marketing Pitch .pdf
Normal file
BIN
poweron/strategy/PowerOn Playground - Marketing Pitch .pdf
Normal file
Binary file not shown.
BIN
poweron/strategy/PowerOn Produktstrategie Product-Market-Fit.pdf
Normal file
BIN
poweron/strategy/PowerOn Produktstrategie Product-Market-Fit.pdf
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
27
templates/convert_md.bat
Normal file
27
templates/convert_md.bat
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
@echo off
|
||||
REM PowerON Markdown to HTML Converter - Windows Batch Script
|
||||
REM Verwendung: convert_md.bat [markdown-datei] [output-datei]
|
||||
|
||||
if "%1"=="" (
|
||||
echo PowerON Markdown zu HTML Konverter
|
||||
echo.
|
||||
echo Verwendung:
|
||||
echo convert_md.bat document.md
|
||||
echo convert_md.bat document.md output.html
|
||||
echo convert_md.bat -d ./docs
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
python md_to_html_converter.py %*
|
||||
|
||||
if %ERRORLEVEL% EQU 0 (
|
||||
echo.
|
||||
echo Konvertierung erfolgreich abgeschlossen!
|
||||
) else (
|
||||
echo.
|
||||
echo Fehler bei der Konvertierung!
|
||||
)
|
||||
|
||||
pause
|
||||
660
templates/md_to_html_converter.py
Normal file
660
templates/md_to_html_converter.py
Normal file
|
|
@ -0,0 +1,660 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
PowerON Markdown to HTML Converter
|
||||
Konvertiert Markdown-Dateien zu HTML mit PowerON-Styling
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
# Einfache Markdown-zu-HTML Konvertierung ohne externe Abhängigkeiten
|
||||
def _convert_markdown_to_html(markdown_text):
|
||||
"""Einfache Markdown-zu-HTML Konvertierung ohne externe Bibliotheken"""
|
||||
|
||||
# HTML-Escaping
|
||||
def escape_html(text):
|
||||
return (text.replace('&', '&')
|
||||
.replace('<', '<')
|
||||
.replace('>', '>')
|
||||
.replace('"', '"')
|
||||
.replace("'", '''))
|
||||
|
||||
# Code-Blöcke zuerst verarbeiten (vor anderen Formatierungen)
|
||||
def process_code_blocks(text):
|
||||
# Fenced code blocks (```)
|
||||
def replace_code_block(match):
|
||||
language = match.group(1) or ''
|
||||
code = match.group(2)
|
||||
return f'<pre><code class="language-{language}">{escape_html(code)}</code></pre>'
|
||||
|
||||
text = re.sub(r'```(\w+)?\n(.*?)\n```', replace_code_block, text, flags=re.DOTALL)
|
||||
|
||||
# Inline code (`)
|
||||
text = re.sub(r'`([^`]+)`', r'<code>\1</code>', text)
|
||||
|
||||
return text
|
||||
|
||||
# Headers
|
||||
def process_headers(text):
|
||||
text = re.sub(r'^###### (.*?)$', r'<h6>\1</h6>', text, flags=re.MULTILINE)
|
||||
text = re.sub(r'^##### (.*?)$', r'<h5>\1</h5>', text, flags=re.MULTILINE)
|
||||
text = re.sub(r'^#### (.*?)$', r'<h4>\1</h4>', text, flags=re.MULTILINE)
|
||||
text = re.sub(r'^### (.*?)$', r'<h3>\1</h3>', text, flags=re.MULTILINE)
|
||||
text = re.sub(r'^## (.*?)$', r'<h2>\1</h2>', text, flags=re.MULTILINE)
|
||||
text = re.sub(r'^# (.*?)$', r'<h1>\1</h1>', text, flags=re.MULTILINE)
|
||||
return text
|
||||
|
||||
# Listen
|
||||
def process_lists(text):
|
||||
lines = text.split('\n')
|
||||
in_ul = False
|
||||
in_ol = False
|
||||
result = []
|
||||
|
||||
for line in lines:
|
||||
# Ungeordnete Listen
|
||||
if re.match(r'^\s*[-*+]\s+', line):
|
||||
if in_ol:
|
||||
result.append('</ol>')
|
||||
in_ol = False
|
||||
if not in_ul:
|
||||
result.append('<ul>')
|
||||
in_ul = True
|
||||
item = re.sub(r'^\s*[-*+]\s+', '', line)
|
||||
result.append(f'<li>{item}</li>')
|
||||
# Geordnete Listen
|
||||
elif re.match(r'^\s*\d+\.\s+', line):
|
||||
if in_ul:
|
||||
result.append('</ul>')
|
||||
in_ul = False
|
||||
if not in_ol:
|
||||
result.append('<ol>')
|
||||
in_ol = True
|
||||
item = re.sub(r'^\s*\d+\.\s+', '', line)
|
||||
result.append(f'<li>{item}</li>')
|
||||
else:
|
||||
if in_ul:
|
||||
result.append('</ul>')
|
||||
in_ul = False
|
||||
if in_ol:
|
||||
result.append('</ol>')
|
||||
in_ol = False
|
||||
result.append(line)
|
||||
|
||||
if in_ul:
|
||||
result.append('</ul>')
|
||||
if in_ol:
|
||||
result.append('</ol>')
|
||||
|
||||
return '\n'.join(result)
|
||||
|
||||
# Links und Bilder
|
||||
def process_links_and_images(text):
|
||||
# Bilder 
|
||||
text = re.sub(r'!\[([^\]]*)\]\(([^)]+)\)', r'<img src="\2" alt="\1">', text)
|
||||
# Links [text](url)
|
||||
text = re.sub(r'\[([^\]]+)\]\(([^)]+)\)', r'<a href="\2">\1</a>', text)
|
||||
return text
|
||||
|
||||
# Bold und Italic
|
||||
def process_emphasis(text):
|
||||
# Bold **text**
|
||||
text = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', text)
|
||||
# Italic *text*
|
||||
text = re.sub(r'\*(.*?)\*', r'<em>\1</em>', text)
|
||||
return text
|
||||
|
||||
# Blockquotes
|
||||
def process_blockquotes(text):
|
||||
lines = text.split('\n')
|
||||
in_quote = False
|
||||
result = []
|
||||
|
||||
for line in lines:
|
||||
if line.strip().startswith('>'):
|
||||
if not in_quote:
|
||||
result.append('<blockquote>')
|
||||
in_quote = True
|
||||
quote_text = line.strip()[1:].strip()
|
||||
result.append(f'<p>{quote_text}</p>')
|
||||
else:
|
||||
if in_quote:
|
||||
result.append('</blockquote>')
|
||||
in_quote = False
|
||||
result.append(line)
|
||||
|
||||
if in_quote:
|
||||
result.append('</blockquote>')
|
||||
|
||||
return '\n'.join(result)
|
||||
|
||||
# Tabellen
|
||||
def process_tables(text):
|
||||
lines = text.split('\n')
|
||||
result = []
|
||||
i = 0
|
||||
|
||||
while i < len(lines):
|
||||
line = lines[i].strip()
|
||||
|
||||
# Prüfe ob es eine Tabellenzeile ist (enthält |)
|
||||
if '|' in line and not line.startswith('<'):
|
||||
table_lines = []
|
||||
j = i
|
||||
|
||||
# Sammle alle aufeinanderfolgenden Tabellenzeilen
|
||||
while j < len(lines) and '|' in lines[j].strip() and not lines[j].strip().startswith('<'):
|
||||
table_lines.append(lines[j].strip())
|
||||
j += 1
|
||||
|
||||
if len(table_lines) >= 2: # Mindestens Header + Separator
|
||||
# Erstelle HTML-Tabelle
|
||||
table_html = ['<table>']
|
||||
|
||||
# Header-Zeile
|
||||
header_cells = [cell.strip() for cell in table_lines[0].split('|')[1:-1]]
|
||||
table_html.append('<thead><tr>')
|
||||
for cell in header_cells:
|
||||
table_html.append(f'<th>{cell}</th>')
|
||||
table_html.append('</tr></thead>')
|
||||
|
||||
# Separator-Zeile überspringen
|
||||
if len(table_lines) > 1 and '---' in table_lines[1]:
|
||||
data_start = 2
|
||||
else:
|
||||
data_start = 1
|
||||
|
||||
# Daten-Zeilen
|
||||
if len(table_lines) > data_start:
|
||||
table_html.append('<tbody>')
|
||||
for row in table_lines[data_start:]:
|
||||
if '|' in row:
|
||||
data_cells = [cell.strip() for cell in row.split('|')[1:-1]]
|
||||
table_html.append('<tr>')
|
||||
for cell in data_cells:
|
||||
table_html.append(f'<td>{cell}</td>')
|
||||
table_html.append('</tr>')
|
||||
table_html.append('</tbody>')
|
||||
|
||||
table_html.append('</table>')
|
||||
result.append('\n'.join(table_html))
|
||||
|
||||
i = j - 1 # -1 weil i am Ende des Loops erhöht wird
|
||||
else:
|
||||
result.append(f'<p>{line}</p>')
|
||||
else:
|
||||
result.append(f'<p>{line}</p>')
|
||||
|
||||
i += 1
|
||||
|
||||
return '\n'.join(result)
|
||||
|
||||
# Horizontale Linien
|
||||
def process_hr(text):
|
||||
text = re.sub(r'^---$', '<hr>', text, flags=re.MULTILINE)
|
||||
return text
|
||||
|
||||
# Paragraphen - Jeder Zeilenumbruch wird zu einem <p> Tag
|
||||
def process_paragraphs(text):
|
||||
lines = text.split('\n')
|
||||
result = []
|
||||
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
if line:
|
||||
# Nur wenn es nicht schon ein HTML-Tag ist
|
||||
if not re.match(r'<[h1-6]|<ul|<ol|<blockquote|<pre|<hr|<li|<table|<thead|<tbody|<tr|<th|<td', line):
|
||||
result.append(f'<p>{line}</p>')
|
||||
else:
|
||||
result.append(line)
|
||||
else:
|
||||
# Leere Zeilen werden zu leeren <p> Tags
|
||||
result.append('<p></p>')
|
||||
|
||||
return '\n'.join(result)
|
||||
|
||||
# Verarbeitung in der richtigen Reihenfolge
|
||||
text = markdown_text
|
||||
|
||||
# Code-Blöcke zuerst (vor anderen Formatierungen)
|
||||
text = process_code_blocks(text)
|
||||
|
||||
# Headers
|
||||
text = process_headers(text)
|
||||
|
||||
# Tabellen
|
||||
text = process_tables(text)
|
||||
|
||||
# Blockquotes
|
||||
text = process_blockquotes(text)
|
||||
|
||||
# Listen
|
||||
text = process_lists(text)
|
||||
|
||||
# Links und Bilder
|
||||
text = process_links_and_images(text)
|
||||
|
||||
# Emphasis
|
||||
text = process_emphasis(text)
|
||||
|
||||
# Horizontale Linien
|
||||
text = process_hr(text)
|
||||
|
||||
# Paragraphen
|
||||
text = process_paragraphs(text)
|
||||
|
||||
return text
|
||||
|
||||
class PowerONHTMLConverter:
|
||||
def __init__(self, css_file="poweron-styles.css"):
|
||||
self.css_file = css_file
|
||||
|
||||
def create_html_template(self, title, content, css_path=None):
|
||||
"""Erstellt HTML-Template mit PowerON-Styling"""
|
||||
if css_path is None:
|
||||
css_path = self.css_file
|
||||
|
||||
html_template = f"""<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="icon" href="/poweron-favicon.png" type="image/png">
|
||||
<title>{title} | PowerON</title>
|
||||
<meta name="description" content="PowerON - KI für Unternehmen | {title}">
|
||||
<meta name="author" content="PowerON">
|
||||
|
||||
<!-- Open Graph Meta Tags -->
|
||||
<meta property="og:title" content="{title} | PowerON">
|
||||
<meta property="og:description" content="PowerON - KI für Unternehmen | {title}">
|
||||
<meta property="og:type" content="article">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,400;0,500;0,700;1,400&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- PowerON Styles -->
|
||||
<link rel="stylesheet" href="{css_path}">
|
||||
|
||||
<!-- Inline CSS als Fallback -->
|
||||
<style>
|
||||
/* PowerON Base Styles - Fallback */
|
||||
body {{
|
||||
font-family: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
line-height: 1.6;
|
||||
color: #1a1a1a;
|
||||
background-color: #ffffff;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}}
|
||||
|
||||
.header {{
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(10px);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
padding: 1rem 0;
|
||||
}}
|
||||
|
||||
.navbar {{
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}}
|
||||
|
||||
.logo {{
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
color: #1a1a1a;
|
||||
text-decoration: none;
|
||||
}}
|
||||
|
||||
.footer {{
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
padding: 2rem 0;
|
||||
text-align: center;
|
||||
margin-top: 4rem;
|
||||
}}
|
||||
|
||||
.container {{
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 1rem;
|
||||
}}
|
||||
</style>
|
||||
|
||||
<!-- Additional Styles for Markdown Content -->
|
||||
<style>
|
||||
/* Markdown Content Styling */
|
||||
.markdown-content {{
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 2rem;
|
||||
line-height: 1.7;
|
||||
}}
|
||||
|
||||
.markdown-content h1 {{
|
||||
border-bottom: 3px solid #4B73FF;
|
||||
padding-bottom: 0.5rem;
|
||||
margin-bottom: 2rem;
|
||||
}}
|
||||
|
||||
.markdown-content h2 {{
|
||||
border-bottom: 2px solid #e5e5e5;
|
||||
padding-bottom: 0.3rem;
|
||||
margin-top: 2.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}}
|
||||
|
||||
.markdown-content h3 {{
|
||||
color: #4B73FF;
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
}}
|
||||
|
||||
.markdown-content h4 {{
|
||||
color: #6b7280;
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0.75rem;
|
||||
}}
|
||||
|
||||
.markdown-content blockquote {{
|
||||
border-left: 4px solid #4B73FF;
|
||||
background: #f8fafc;
|
||||
padding: 1rem 1.5rem;
|
||||
margin: 1.5rem 0;
|
||||
border-radius: 0 8px 8px 0;
|
||||
font-style: italic;
|
||||
}}
|
||||
|
||||
.markdown-content code {{
|
||||
background: #f1f5f9;
|
||||
padding: 0.2rem 0.4rem;
|
||||
border-radius: 4px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 0.9em;
|
||||
color: #e11d48;
|
||||
}}
|
||||
|
||||
.markdown-content pre {{
|
||||
background: #1e293b;
|
||||
color: #e2e8f0;
|
||||
padding: 1.5rem;
|
||||
border-radius: 8px;
|
||||
overflow-x: auto;
|
||||
margin: 1.5rem 0;
|
||||
}}
|
||||
|
||||
.markdown-content pre code {{
|
||||
background: none;
|
||||
padding: 0;
|
||||
color: inherit;
|
||||
font-size: 0.9em;
|
||||
}}
|
||||
|
||||
.markdown-content table {{
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 1.5rem 0;
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
|
||||
}}
|
||||
|
||||
.markdown-content th {{
|
||||
background: #4B73FF;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
}}
|
||||
|
||||
.markdown-content td {{
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
}}
|
||||
|
||||
.markdown-content tr:hover {{
|
||||
background: #f8fafc;
|
||||
}}
|
||||
|
||||
.markdown-content ul, .markdown-content ol {{
|
||||
margin: 1rem 0;
|
||||
padding-left: 2rem;
|
||||
}}
|
||||
|
||||
.markdown-content li {{
|
||||
margin: 0.5rem 0;
|
||||
}}
|
||||
|
||||
.markdown-content img {{
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 8px;
|
||||
margin: 1.5rem 0;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
}}
|
||||
|
||||
.markdown-content a {{
|
||||
color: #4B73FF;
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid transparent;
|
||||
transition: all 0.3s ease;
|
||||
}}
|
||||
|
||||
.markdown-content a:hover {{
|
||||
border-bottom-color: #4B73FF;
|
||||
}}
|
||||
|
||||
.markdown-content hr {{
|
||||
border: none;
|
||||
height: 2px;
|
||||
background: linear-gradient(90deg, transparent, #4B73FF, transparent);
|
||||
margin: 3rem 0;
|
||||
}}
|
||||
|
||||
/* Table of Contents */
|
||||
.toc {{
|
||||
background: #f8fafc;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 8px;
|
||||
padding: 1.5rem;
|
||||
margin: 2rem 0;
|
||||
}}
|
||||
|
||||
.toc h2 {{
|
||||
margin-top: 0;
|
||||
color: #1a1a1a;
|
||||
border-bottom: 2px solid #4B73FF;
|
||||
padding-bottom: 0.5rem;
|
||||
}}
|
||||
|
||||
.toc ul {{
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}}
|
||||
|
||||
.toc li {{
|
||||
margin: 0.5rem 0;
|
||||
}}
|
||||
|
||||
.toc a {{
|
||||
color: #6b7280;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}}
|
||||
|
||||
.toc a:hover {{
|
||||
color: #4B73FF;
|
||||
}}
|
||||
|
||||
/* Responsive */
|
||||
@media (max-width: 768px) {{
|
||||
.markdown-content {{
|
||||
padding: 1rem;
|
||||
}}
|
||||
|
||||
.markdown-content h1 {{
|
||||
font-size: 2.5rem;
|
||||
}}
|
||||
|
||||
.markdown-content h2 {{
|
||||
font-size: 2rem;
|
||||
}}
|
||||
|
||||
.markdown-content h3 {{
|
||||
font-size: 1.5rem;
|
||||
}}
|
||||
}}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Header -->
|
||||
<header class="header">
|
||||
<div class="navbar">
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main style="margin-top: 80px;">
|
||||
<div class="markdown-content">
|
||||
{content}
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<p>© 2024 PowerON - KI für Unternehmen. Alle Rechte vorbehalten.</p>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
return html_template
|
||||
|
||||
def convert_markdown_file(self, input_file, output_file=None, css_path=None):
|
||||
"""Konvertiert eine Markdown-Datei zu HTML"""
|
||||
input_path = Path(input_file)
|
||||
|
||||
if not input_path.exists():
|
||||
raise FileNotFoundError(f"Markdown-Datei nicht gefunden: {input_file}")
|
||||
|
||||
# Output-Datei bestimmen
|
||||
if output_file is None:
|
||||
output_file = input_path.with_suffix('.html')
|
||||
else:
|
||||
output_file = Path(output_file)
|
||||
|
||||
# Markdown lesen und konvertieren
|
||||
with open(input_path, 'r', encoding='utf-8') as f:
|
||||
markdown_content = f.read()
|
||||
|
||||
# Titel aus Markdown extrahieren (erste H1)
|
||||
title_match = re.search(r'^#\s+(.+)$', markdown_content, re.MULTILINE)
|
||||
title = title_match.group(1) if title_match else input_path.stem
|
||||
|
||||
# Markdown zu HTML konvertieren
|
||||
html_content = _convert_markdown_to_html(markdown_content)
|
||||
|
||||
# HTML-Template erstellen
|
||||
full_html = self.create_html_template(title, html_content, css_path)
|
||||
|
||||
# HTML-Datei schreiben
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(full_html)
|
||||
|
||||
print(f"Konvertiert: {input_file} -> {output_file}")
|
||||
return output_file
|
||||
|
||||
def convert_directory(self, input_dir, output_dir=None, css_path=None):
|
||||
"""Konvertiert alle Markdown-Dateien in einem Verzeichnis"""
|
||||
input_path = Path(input_dir)
|
||||
|
||||
if not input_path.exists():
|
||||
raise FileNotFoundError(f"Verzeichnis nicht gefunden: {input_dir}")
|
||||
|
||||
if output_dir is None:
|
||||
output_dir = input_path / "html_output"
|
||||
else:
|
||||
output_dir = Path(output_dir)
|
||||
|
||||
output_dir.mkdir(exist_ok=True)
|
||||
|
||||
# Alle .md Dateien finden
|
||||
md_files = list(input_path.glob("**/*.md"))
|
||||
|
||||
if not md_files:
|
||||
print(f"⚠️ Keine Markdown-Dateien gefunden in: {input_dir}")
|
||||
return
|
||||
|
||||
print(f"📁 Konvertiere {len(md_files)} Markdown-Dateien...")
|
||||
|
||||
for md_file in md_files:
|
||||
# Relativen Pfad beibehalten
|
||||
relative_path = md_file.relative_to(input_path)
|
||||
output_file = output_dir / relative_path.with_suffix('.html')
|
||||
|
||||
# Verzeichnis erstellen falls nötig
|
||||
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
try:
|
||||
self.convert_markdown_file(md_file, output_file, css_path)
|
||||
except Exception as e:
|
||||
print(f"❌ Fehler bei {md_file}: {e}")
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="PowerON Markdown zu HTML Konverter",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog="""
|
||||
Beispiele:
|
||||
python md_to_html_converter.py document.md
|
||||
python md_to_html_converter.py document.md -o output.html
|
||||
python md_to_html_converter.py -d ./docs -o ./html_output
|
||||
python md_to_html_converter.py document.md -c ../styles/custom.css
|
||||
"""
|
||||
)
|
||||
|
||||
parser.add_argument('input', nargs='?', help='Markdown-Datei oder Verzeichnis')
|
||||
parser.add_argument('-o', '--output', help='Output-Datei oder -verzeichnis')
|
||||
parser.add_argument('-d', '--directory', help='Verzeichnis mit Markdown-Dateien konvertieren')
|
||||
parser.add_argument('-c', '--css', default='poweron-styles.css', help='CSS-Datei (Standard: poweron-styles.css)')
|
||||
parser.add_argument('--version', action='version', version='PowerON MD to HTML Converter 1.0')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.input and not args.directory:
|
||||
parser.print_help()
|
||||
return
|
||||
|
||||
try:
|
||||
converter = PowerONHTMLConverter(args.css)
|
||||
|
||||
if args.directory:
|
||||
converter.convert_directory(args.directory, args.output, args.css)
|
||||
else:
|
||||
converter.convert_markdown_file(args.input, args.output, args.css)
|
||||
|
||||
print("Konvertierung abgeschlossen!")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Fehler: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
BIN
templates/poweron-styles.css
Normal file
BIN
templates/poweron-styles.css
Normal file
Binary file not shown.
Loading…
Reference in a new issue