word generation
This commit is contained in:
parent
c91e4de4a8
commit
5b8a8b7572
6 changed files with 428 additions and 235 deletions
BIN
assets/antrag_vorlage.docx
Normal file
BIN
assets/antrag_vorlage.docx
Normal file
Binary file not shown.
|
|
@ -31,7 +31,6 @@
|
||||||
jinja2
|
jinja2
|
||||||
google-generativeai # Dependency for Gemini API
|
google-generativeai # Dependency for Gemini API
|
||||||
grpcio # Required by google-generativeai
|
grpcio # Required by google-generativeai
|
||||||
reportlab # Dependency for PDF generation
|
|
||||||
python-docx # Dependency for Word document generation
|
python-docx # Dependency for Word document generation
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
294
meinantrag.py
294
meinantrag.py
|
|
@ -13,11 +13,7 @@ from jinja2 import Environment, FileSystemLoader
|
||||||
import google.generativeai as genai
|
import google.generativeai as genai
|
||||||
import re
|
import re
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from reportlab.lib.pagesizes import A4
|
from datetime import datetime
|
||||||
from reportlab.lib.units import cm
|
|
||||||
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
|
||||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
|
|
||||||
from reportlab.lib.enums import TA_LEFT, TA_JUSTIFY
|
|
||||||
try:
|
try:
|
||||||
from docx import Document
|
from docx import Document
|
||||||
from docx.shared import Pt, Inches
|
from docx.shared import Pt, Inches
|
||||||
|
|
@ -84,8 +80,8 @@ class MeinAntragApp(BaseTemplateResource):
|
||||||
template = self.jinja_env.get_template('index.html')
|
template = self.jinja_env.get_template('index.html')
|
||||||
resp.content_type = 'text/html; charset=utf-8'
|
resp.content_type = 'text/html; charset=utf-8'
|
||||||
resp.text = template.render(
|
resp.text = template.render(
|
||||||
meta_title='MeinAntrag – Anfragelinks für FragDenStaat',
|
meta_title='MeinAntrag – Anträge an die Karlsruher Stadtverwaltung',
|
||||||
meta_description='Erstelle vorausgefüllte Anfragelinks für FragDenStaat.de, suche Behörden, füge Betreff und Text hinzu und teile den Link.',
|
meta_description='Erstelle einfach Vorlagen für Anfragen oder Anträge an die Karlsruher Stadtverwaltung zu deinem persönlichen Thema und schicke diese direkt an eine Stadtratsfraktion!',
|
||||||
canonical_url=f"{SITE_BASE_URL}/"
|
canonical_url=f"{SITE_BASE_URL}/"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -301,188 +297,120 @@ WICHTIG:
|
||||||
'error': str(e)
|
'error': str(e)
|
||||||
})
|
})
|
||||||
|
|
||||||
class GeneratePDFResource:
|
|
||||||
def _generate_pdf(self, title, demand, justification, party_name=""):
|
|
||||||
"""Generate a PDF that looks like a city council proposal"""
|
|
||||||
buffer = BytesIO()
|
|
||||||
doc = SimpleDocTemplate(buffer, pagesize=A4,
|
|
||||||
rightMargin=2.5*cm, leftMargin=2.5*cm,
|
|
||||||
topMargin=2.5*cm, bottomMargin=2.5*cm)
|
|
||||||
|
|
||||||
# Container for the 'Flowable' objects
|
|
||||||
story = []
|
|
||||||
|
|
||||||
# Define styles
|
|
||||||
styles = getSampleStyleSheet()
|
|
||||||
|
|
||||||
# Custom styles for the document
|
|
||||||
title_style = ParagraphStyle(
|
|
||||||
'CustomTitle',
|
|
||||||
parent=styles['Heading1'],
|
|
||||||
fontSize=16,
|
|
||||||
textColor='black',
|
|
||||||
spaceAfter=30,
|
|
||||||
alignment=TA_LEFT,
|
|
||||||
fontName='Helvetica-Bold'
|
|
||||||
)
|
|
||||||
|
|
||||||
heading_style = ParagraphStyle(
|
|
||||||
'CustomHeading',
|
|
||||||
parent=styles['Heading2'],
|
|
||||||
fontSize=12,
|
|
||||||
textColor='black',
|
|
||||||
spaceAfter=12,
|
|
||||||
spaceBefore=20,
|
|
||||||
alignment=TA_LEFT,
|
|
||||||
fontName='Helvetica-Bold'
|
|
||||||
)
|
|
||||||
|
|
||||||
body_style = ParagraphStyle(
|
|
||||||
'CustomBody',
|
|
||||||
parent=styles['Normal'],
|
|
||||||
fontSize=11,
|
|
||||||
textColor='black',
|
|
||||||
spaceAfter=12,
|
|
||||||
alignment=TA_JUSTIFY,
|
|
||||||
fontName='Helvetica'
|
|
||||||
)
|
|
||||||
|
|
||||||
# Header with party name if provided
|
|
||||||
if party_name:
|
|
||||||
party_para = Paragraph(f"<b>Antrag der {party_name}</b>", body_style)
|
|
||||||
story.append(party_para)
|
|
||||||
story.append(Spacer(1, 0.5*cm))
|
|
||||||
|
|
||||||
# Title
|
|
||||||
if title:
|
|
||||||
title_para = Paragraph(f"<b>{title}</b>", title_style)
|
|
||||||
story.append(title_para)
|
|
||||||
|
|
||||||
# Demand section
|
|
||||||
if demand:
|
|
||||||
story.append(Spacer(1, 0.3*cm))
|
|
||||||
demand_heading = Paragraph("<b>Der Gemeinderat möge beschließen:</b>", heading_style)
|
|
||||||
story.append(demand_heading)
|
|
||||||
|
|
||||||
# Process demand text - replace newlines with proper breaks
|
|
||||||
demand_lines = demand.split('\n')
|
|
||||||
for line in demand_lines:
|
|
||||||
if line.strip():
|
|
||||||
demand_para = Paragraph(line.strip(), body_style)
|
|
||||||
story.append(demand_para)
|
|
||||||
|
|
||||||
# Justification section
|
|
||||||
if justification:
|
|
||||||
story.append(Spacer(1, 0.5*cm))
|
|
||||||
justification_heading = Paragraph("<b>Begründung/Sachverhalt</b>", heading_style)
|
|
||||||
story.append(justification_heading)
|
|
||||||
|
|
||||||
# Process justification text
|
|
||||||
justification_lines = justification.split('\n')
|
|
||||||
for line in justification_lines:
|
|
||||||
if line.strip():
|
|
||||||
justification_para = Paragraph(line.strip(), body_style)
|
|
||||||
story.append(justification_para)
|
|
||||||
|
|
||||||
# Build PDF
|
|
||||||
doc.build(story)
|
|
||||||
buffer.seek(0)
|
|
||||||
return buffer
|
|
||||||
|
|
||||||
def on_post(self, req, resp):
|
|
||||||
"""Generate PDF from form data"""
|
|
||||||
try:
|
|
||||||
# Get form data
|
|
||||||
title = req.get_param('title', default='') or ''
|
|
||||||
demand = req.get_param('demand', default='') or ''
|
|
||||||
justification = req.get_param('justification', default='') or ''
|
|
||||||
party_name = req.get_param('party_name', default='') or ''
|
|
||||||
|
|
||||||
# If empty, try to read from stream
|
|
||||||
if not title:
|
|
||||||
try:
|
|
||||||
stream = getattr(req, 'bounded_stream', req.stream)
|
|
||||||
raw_body = stream.read().decode('utf-8')
|
|
||||||
parsed = parse_qs(raw_body)
|
|
||||||
title = parsed.get('title', [''])[0]
|
|
||||||
demand = parsed.get('demand', [''])[0]
|
|
||||||
justification = parsed.get('justification', [''])[0]
|
|
||||||
party_name = parsed.get('party_name', [''])[0]
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Generate PDF
|
|
||||||
pdf_buffer = self._generate_pdf(title, demand, justification, party_name)
|
|
||||||
|
|
||||||
# Return PDF
|
|
||||||
resp.content_type = 'application/pdf'
|
|
||||||
resp.set_header('Content-Disposition', 'inline; filename="antrag.pdf"')
|
|
||||||
resp.data = pdf_buffer.read()
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
import traceback
|
|
||||||
traceback.print_exc()
|
|
||||||
resp.status = falcon.HTTP_500
|
|
||||||
resp.content_type = 'application/json'
|
|
||||||
resp.text = json.dumps({
|
|
||||||
'success': False,
|
|
||||||
'error': str(e)
|
|
||||||
})
|
|
||||||
|
|
||||||
class GenerateWordResource:
|
class GenerateWordResource:
|
||||||
|
def __init__(self):
|
||||||
|
# Get template path
|
||||||
|
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
self.template_path = os.path.join(script_dir, 'assets', 'antrag_vorlage.docx')
|
||||||
|
# Fallback if not in assets
|
||||||
|
if not os.path.exists(self.template_path):
|
||||||
|
assets_dir = os.path.join(script_dir, '..', 'assets')
|
||||||
|
self.template_path = os.path.join(assets_dir, 'antrag_vorlage.docx')
|
||||||
|
|
||||||
def _generate_word(self, title, demand, justification, party_name=""):
|
def _generate_word(self, title, demand, justification, party_name=""):
|
||||||
"""Generate a Word document that looks like a city council proposal"""
|
"""Generate a Word document using the template"""
|
||||||
doc = Document()
|
# Load template
|
||||||
|
if os.path.exists(self.template_path):
|
||||||
|
doc = Document(self.template_path)
|
||||||
|
else:
|
||||||
|
# Fallback: create new document if template not found
|
||||||
|
doc = Document()
|
||||||
|
|
||||||
# Set default font
|
# Get current date in DD.MM.YYYY format
|
||||||
style = doc.styles['Normal']
|
current_date = datetime.now().strftime("%d.%m.%Y")
|
||||||
font = style.font
|
|
||||||
font.name = 'Arial'
|
|
||||||
font.size = Pt(11)
|
|
||||||
|
|
||||||
# Header with party name if provided
|
# Combine demand for ANTRAGSTEXT (with heading)
|
||||||
if party_name:
|
antragtext = "Der Gemeinderat möge beschließen:\n" + demand
|
||||||
party_para = doc.add_paragraph(f"Antrag der {party_name}")
|
|
||||||
party_para.runs[0].bold = True
|
|
||||||
party_para.runs[0].font.size = Pt(11)
|
|
||||||
doc.add_paragraph()
|
|
||||||
|
|
||||||
# Title
|
# Replace placeholders in all paragraphs
|
||||||
if title:
|
for paragraph in doc.paragraphs:
|
||||||
title_para = doc.add_paragraph(title)
|
full_text = paragraph.text
|
||||||
title_para.runs[0].bold = True
|
if not full_text:
|
||||||
title_para.runs[0].font.size = Pt(16)
|
continue
|
||||||
title_para.paragraph_format.space_after = Pt(30)
|
|
||||||
|
|
||||||
# Demand section
|
|
||||||
if demand:
|
|
||||||
doc.add_paragraph()
|
|
||||||
demand_heading = doc.add_paragraph("Der Gemeinderat möge beschließen:")
|
|
||||||
demand_heading.runs[0].bold = True
|
|
||||||
demand_heading.runs[0].font.size = Pt(12)
|
|
||||||
demand_heading.paragraph_format.space_before = Pt(20)
|
|
||||||
demand_heading.paragraph_format.space_after = Pt(12)
|
|
||||||
|
|
||||||
# Process demand text
|
# Replace FRAKTION
|
||||||
demand_lines = demand.split('\n')
|
if party_name and 'FRAKTION' in full_text:
|
||||||
for line in demand_lines:
|
for run in paragraph.runs:
|
||||||
if line.strip():
|
if 'FRAKTION' in run.text:
|
||||||
doc.add_paragraph(line.strip())
|
run.text = run.text.replace('FRAKTION', party_name)
|
||||||
|
|
||||||
# Justification section
|
|
||||||
if justification:
|
|
||||||
doc.add_paragraph()
|
|
||||||
justification_heading = doc.add_paragraph("Begründung/Sachverhalt")
|
|
||||||
justification_heading.runs[0].bold = True
|
|
||||||
justification_heading.runs[0].font.size = Pt(12)
|
|
||||||
justification_heading.paragraph_format.space_before = Pt(20)
|
|
||||||
justification_heading.paragraph_format.space_after = Pt(12)
|
|
||||||
|
|
||||||
# Process justification text
|
# Replace XX.XX.XXXX with current date
|
||||||
justification_lines = justification.split('\n')
|
if 'XX.XX.XXXX' in full_text:
|
||||||
for line in justification_lines:
|
for run in paragraph.runs:
|
||||||
if line.strip():
|
if 'XX.XX.XXXX' in run.text:
|
||||||
doc.add_paragraph(line.strip())
|
run.text = run.text.replace('XX.XX.XXXX', current_date)
|
||||||
|
|
||||||
|
# Replace ANTRAGSTITEL (bold)
|
||||||
|
if 'ANTRAGSTITEL' in full_text:
|
||||||
|
paragraph.clear()
|
||||||
|
run = paragraph.add_run(title)
|
||||||
|
run.bold = True
|
||||||
|
|
||||||
|
# Replace ANTRAGSTEXT
|
||||||
|
if 'ANTRAGSTEXT' in full_text:
|
||||||
|
paragraph.clear()
|
||||||
|
lines = antragtext.split('\n')
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if line.strip():
|
||||||
|
run = paragraph.add_run(line.strip())
|
||||||
|
if i == 0: # First line (heading) should be bold
|
||||||
|
run.bold = True
|
||||||
|
if i < len(lines) - 1:
|
||||||
|
paragraph.add_run('\n')
|
||||||
|
|
||||||
|
# Replace BEGRÜNDUNGSTEXT
|
||||||
|
if 'BEGRÜNDUNGSTEXT' in full_text:
|
||||||
|
paragraph.clear()
|
||||||
|
lines = justification.split('\n')
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if line.strip():
|
||||||
|
paragraph.add_run(line.strip())
|
||||||
|
if i < len(lines) - 1:
|
||||||
|
paragraph.add_run('\n')
|
||||||
|
|
||||||
|
# Also check tables for placeholders
|
||||||
|
for table in doc.tables:
|
||||||
|
for row in table.rows:
|
||||||
|
for cell in row.cells:
|
||||||
|
for paragraph in cell.paragraphs:
|
||||||
|
full_text = paragraph.text
|
||||||
|
if not full_text:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if party_name and 'FRAKTION' in full_text:
|
||||||
|
for run in paragraph.runs:
|
||||||
|
if 'FRAKTION' in run.text:
|
||||||
|
run.text = run.text.replace('FRAKTION', party_name)
|
||||||
|
|
||||||
|
if 'XX.XX.XXXX' in full_text:
|
||||||
|
for run in paragraph.runs:
|
||||||
|
if 'XX.XX.XXXX' in run.text:
|
||||||
|
run.text = run.text.replace('XX.XX.XXXX', current_date)
|
||||||
|
|
||||||
|
if 'ANTRAGSTITEL' in full_text:
|
||||||
|
paragraph.clear()
|
||||||
|
run = paragraph.add_run(title)
|
||||||
|
run.bold = True
|
||||||
|
|
||||||
|
if 'ANTRAGSTEXT' in full_text:
|
||||||
|
paragraph.clear()
|
||||||
|
lines = antragtext.split('\n')
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if line.strip():
|
||||||
|
run = paragraph.add_run(line.strip())
|
||||||
|
if i == 0:
|
||||||
|
run.bold = True
|
||||||
|
if i < len(lines) - 1:
|
||||||
|
paragraph.add_run('\n')
|
||||||
|
|
||||||
|
if 'BEGRÜNDUNGSTEXT' in full_text:
|
||||||
|
paragraph.clear()
|
||||||
|
lines = justification.split('\n')
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if line.strip():
|
||||||
|
paragraph.add_run(line.strip())
|
||||||
|
if i < len(lines) - 1:
|
||||||
|
paragraph.add_run('\n')
|
||||||
|
|
||||||
# Save to buffer
|
# Save to buffer
|
||||||
buffer = BytesIO()
|
buffer = BytesIO()
|
||||||
|
|
@ -583,7 +511,6 @@ meinantrag = MeinAntragApp()
|
||||||
impressum = ImpressumResource()
|
impressum = ImpressumResource()
|
||||||
datenschutz = DatenschutzResource()
|
datenschutz = DatenschutzResource()
|
||||||
generate_antrag = GenerateAntragResource()
|
generate_antrag = GenerateAntragResource()
|
||||||
generate_pdf = GeneratePDFResource()
|
|
||||||
generate_word = GenerateWordResource()
|
generate_word = GenerateWordResource()
|
||||||
robots = RobotsResource()
|
robots = RobotsResource()
|
||||||
sitemap = SitemapResource()
|
sitemap = SitemapResource()
|
||||||
|
|
@ -592,7 +519,6 @@ app.add_route('/', meinantrag)
|
||||||
app.add_route('/impressum', impressum)
|
app.add_route('/impressum', impressum)
|
||||||
app.add_route('/datenschutz', datenschutz)
|
app.add_route('/datenschutz', datenschutz)
|
||||||
app.add_route('/api/generate-antrag', generate_antrag)
|
app.add_route('/api/generate-antrag', generate_antrag)
|
||||||
app.add_route('/api/generate-pdf', generate_pdf)
|
|
||||||
app.add_route('/api/generate-word', generate_word)
|
app.add_route('/api/generate-word', generate_word)
|
||||||
app.add_route('/robots.txt', robots)
|
app.add_route('/robots.txt', robots)
|
||||||
app.add_route('/sitemap.xml', sitemap)
|
app.add_route('/sitemap.xml', sitemap)
|
||||||
|
|
|
||||||
|
|
@ -8,20 +8,20 @@
|
||||||
<link href="/static/css/select2.min.css" rel="stylesheet">
|
<link href="/static/css/select2.min.css" rel="stylesheet">
|
||||||
<link href="/static/css/select2-bootstrap-5-theme.min.css" rel="stylesheet">
|
<link href="/static/css/select2-bootstrap-5-theme.min.css" rel="stylesheet">
|
||||||
|
|
||||||
<meta name="description" content="{{ meta_description | default('Erstelle vorausgefüllte FragDenStaat.de-Anfragelinks und teile sie mit Freund:innen. Suche Behörden, füge Betreff und Text hinzu und generiere einen teilbaren Link.') }}">
|
<meta name="description" content="{{ meta_description | default('Erstelle einfach Vorlagen für Anfragen oder Anträge an die Karlsruher Stadtverwaltung zu deinem persönlichen Thema und schicke diese direkt an eine Stadtratsfraktion!') }}">
|
||||||
<link rel="canonical" href="{{ canonical_url | default('/') }}">
|
<link rel="canonical" href="{{ canonical_url | default('/') }}">
|
||||||
<link rel="alternate" hreflang="de" href="{{ canonical_url | default('/') }}">
|
<link rel="alternate" hreflang="de" href="{{ canonical_url | default('/') }}">
|
||||||
|
|
||||||
<meta property="og:type" content="website">
|
<meta property="og:type" content="website">
|
||||||
<meta property="og:site_name" content="MeinAntrag">
|
<meta property="og:site_name" content="MeinAntrag">
|
||||||
<meta property="og:title" content="{{ meta_title | default('MeinAntrag') }}">
|
<meta property="og:title" content="{{ meta_title | default('MeinAntrag') }}">
|
||||||
<meta property="og:description" content="{{ meta_description | default('Erstelle vorausgefüllte FragDenStaat.de-Anfragelinks und teile sie mit Freund:innen.') }}">
|
<meta property="og:description" content="{{ meta_description | default('Erstelle einfach Vorlagen für Anfragen oder Anträge an die Karlsruher Stadtverwaltung zu deinem persönlichen Thema und schicke diese direkt an eine Stadtratsfraktion!') }}">
|
||||||
<meta property="og:locale" content="de_DE">
|
<meta property="og:locale" content="de_DE">
|
||||||
<meta property="og:url" content="{{ canonical_url | default('/') }}">
|
<meta property="og:url" content="{{ canonical_url | default('/') }}">
|
||||||
|
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
<meta name="twitter:title" content="{{ meta_title | default('MeinAntrag') }}">
|
<meta name="twitter:title" content="{{ meta_title | default('MeinAntrag') }}">
|
||||||
<meta name="twitter:description" content="{{ meta_description | default('Erstelle vorausgefüllte FragDenStaat.de-Anfragelinks und teile sie mit Freund:innen.') }}">
|
<meta name="twitter:description" content="{{ meta_description | default('Erstelle einfach Vorlagen für Anfragen oder Anträge an die Karlsruher Stadtverwaltung zu deinem persönlichen Thema und schicke diese direkt an eine Stadtratsfraktion!') }}">
|
||||||
|
|
||||||
{% if noindex %}<meta name="robots" content="noindex,follow">{% endif %}
|
{% if noindex %}<meta name="robots" content="noindex,follow">{% endif %}
|
||||||
<meta name="theme-color" content="#667eea">
|
<meta name="theme-color" content="#667eea">
|
||||||
|
|
|
||||||
|
|
@ -69,13 +69,6 @@
|
||||||
</svg>
|
</svg>
|
||||||
<span id="mailBtnText">Mail an Fraktion senden</span>
|
<span id="mailBtnText">Mail an Fraktion senden</span>
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="btn btn-primary" id="pdfBtn">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-pdf me-2" viewBox="0 0 16 16">
|
|
||||||
<path d="M8.5 6a.5.5 0 0 0-1 0v1.5H6a.5.5 0 0 0 0 1h1.5V10a.5.5 0 0 0 1 0V8.5H10a.5.5 0 0 0 0-1H8.5z"/>
|
|
||||||
<path d="M14 14V4.5L9.5 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2M9.5 3A1.5 1.5 0 0 0 11 4.5h2V14a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1h5.5z"/>
|
|
||||||
</svg>
|
|
||||||
PDF anzeigen
|
|
||||||
</button>
|
|
||||||
<button type="button" class="btn btn-primary" id="wordBtn">
|
<button type="button" class="btn btn-primary" id="wordBtn">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-word me-2" viewBox="0 0 16 16">
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file-earmark-word me-2" viewBox="0 0 16 16">
|
||||||
<path d="M5.485 6.879a.5.5 0 1 0-.97.242l1.5 6a.5.5 0 0 0 .539.314l1.5-.5a.5.5 0 0 0 .186-.596l-.737-2.945 2.679-3.42a.5.5 0 1 0-.758-.652L6.978 8.616l-1.493-.5z"/>
|
<path d="M5.485 6.879a.5.5 0 1 0-.97.242l1.5 6a.5.5 0 0 0 .539.314l1.5-.5a.5.5 0 0 0 .186-.596l-.737-2.945 2.679-3.42a.5.5 0 1 0-.758-.652L6.978 8.616l-1.493-.5z"/>
|
||||||
|
|
@ -217,46 +210,6 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle PDF button click
|
|
||||||
$('#pdfBtn').on('click', function() {
|
|
||||||
const title = $('#antragstitel').val() || '';
|
|
||||||
const demand = $('#forderung').val() || '';
|
|
||||||
const justification = $('#begruendung').val() || '';
|
|
||||||
const partyName = $('#resultFields').data('party-name') || '';
|
|
||||||
|
|
||||||
// Prepare form data
|
|
||||||
const formData = new URLSearchParams();
|
|
||||||
formData.append('title', title);
|
|
||||||
formData.append('demand', demand);
|
|
||||||
formData.append('justification', justification);
|
|
||||||
if (partyName) {
|
|
||||||
formData.append('party_name', partyName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open PDF in new window
|
|
||||||
fetch('/api/generate-pdf', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded'
|
|
||||||
},
|
|
||||||
body: formData.toString()
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Fehler beim Generieren des PDFs');
|
|
||||||
}
|
|
||||||
return response.blob();
|
|
||||||
})
|
|
||||||
.then(blob => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
window.open(url, '_blank');
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
alert('Fehler beim Generieren des PDFs: ' + error.message);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle Word button click
|
// Handle Word button click
|
||||||
$('#wordBtn').on('click', function() {
|
$('#wordBtn').on('click', function() {
|
||||||
const title = $('#antragstitel').val() || '';
|
const title = $('#antragstitel').val() || '';
|
||||||
|
|
|
||||||
315
vorlage.html
Normal file
315
vorlage.html
Normal file
|
|
@ -0,0 +1,315 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||||
|
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||||
|
<link type="text/css" href="https://pages.github.com/css/pages.css" media="all" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Begin Jekyll SEO tag v2.8.0 -->
|
||||||
|
<title>GitHub Pages | Websites for you and your projects, hosted directly from your GitHub repository. Just edit, push, and your changes are live.</title>
|
||||||
|
<meta name="generator" content="Jekyll v3.10.0" />
|
||||||
|
<meta property="og:title" content="GitHub Pages" />
|
||||||
|
<meta property="og:locale" content="en_US" />
|
||||||
|
<meta name="description" content="Websites for you and your projects, hosted directly from your GitHub repository. Just edit, push, and your changes are live." />
|
||||||
|
<meta property="og:description" content="Websites for you and your projects, hosted directly from your GitHub repository. Just edit, push, and your changes are live." />
|
||||||
|
<link rel="canonical" href="https://pages.github.com/" />
|
||||||
|
<meta property="og:url" content="https://pages.github.com/" />
|
||||||
|
<meta property="og:site_name" content="GitHub Pages" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
|
<meta name="twitter:card" content="summary" />
|
||||||
|
<meta property="twitter:title" content="GitHub Pages" />
|
||||||
|
<meta name="twitter:site" content="@github" />
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{"@context":"https://schema.org","@type":"WebSite","description":"Websites for you and your projects, hosted directly from your GitHub repository. Just edit, push, and your changes are live.","headline":"GitHub Pages","name":"GitHub Pages","url":"https://pages.github.com/"}</script>
|
||||||
|
<!-- End Jekyll SEO tag -->
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="home ">
|
||||||
|
|
||||||
|
|
||||||
|
<section id="hero-spot" class="hero-spot">
|
||||||
|
<a href="/"><img src="https://pages.github.com/images/logo.svg" alt="GitHub Pages" class="logo" /></a>
|
||||||
|
|
||||||
|
<h1>Websites for you and your projects.</h1>
|
||||||
|
<h2>Hosted directly from your <a href="https://github.com">GitHub repository</a>. Just edit, push, and your changes are live.</h2>
|
||||||
|
|
||||||
|
<a href="https://help.github.com/pages/" class="help-link">Pages Help</a>
|
||||||
|
|
||||||
|
<div id="slideshow">
|
||||||
|
<img src="https://pages.github.com/images/slideshow/bootstrap.png" alt="Bootstrap" class="slide active" width="893" />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="tutorial" class="tutorial">
|
||||||
|
<h1>Ready to get started? Build your own site from scratch or generate one for your project.</h1>
|
||||||
|
<h2>You get one site per GitHub account and organization, <br />and unlimited project sites. Let‘s get started.</h2>
|
||||||
|
|
||||||
|
<ul class="tabs">
|
||||||
|
<li><a href="#user-site" class="selected">User or organization site</a></li>
|
||||||
|
<li><a href="#project-site">Project site</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<!-- ### Start of tutorials -->
|
||||||
|
<ul id="user-site" class="tutorial-list wrapper active">
|
||||||
|
<li id="create-repo-step" class="image-right">
|
||||||
|
<h4>Create a repository</h4>
|
||||||
|
<p>Head over to <a href="https://github.com">GitHub</a> and <a data-proofer-ignore="true" href="https://github.com/new">create a new public repository</a> named <em>username</em>.github.io, where <em>username</em> is your username (or organization name) on GitHub.</p>
|
||||||
|
|
||||||
|
<p class="details">If the first part of the repository doesn’t exactly match your username, it won’t work, so make sure to get it right.</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="question">
|
||||||
|
<h4>What git client are you using?</h4>
|
||||||
|
<ul class="tabs">
|
||||||
|
<li><a id="option-terminal" href="#terminal-step-1" class="selected">A terminal</a></li>
|
||||||
|
<li><a id="option-desktop" href="#setup-in-desktop">GitHub Desktop</a></li>
|
||||||
|
<li><a id="option-newuser" href="#new-user-step-1">I don't know</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li id="new-user-step-1" class="option-newuser">
|
||||||
|
<h4>Download GitHub Desktop</h4>
|
||||||
|
<p>GitHub Desktop is a great way to use Git and GitHub on macOS and Windows.</p>
|
||||||
|
|
||||||
|
<a class="desktop-download" href="https://desktop.github.com"><span class="icon"></span>Download GitHub Desktop</a>
|
||||||
|
|
||||||
|
<img src="https://pages.github.com/images/dashboard@2x.png" width="1054" alt="GitHub Desktop screenshot" class="full-size" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li id="terminal-step-1" class="option-terminal">
|
||||||
|
<h4>Clone the repository</h4>
|
||||||
|
<p>Go to the folder where you want to store your project, and clone the new repository:</p>
|
||||||
|
|
||||||
|
<div class="terminal">
|
||||||
|
<div class="header"></div>
|
||||||
|
<div class="shell">
|
||||||
|
<p><span class="path">~</span><span class="prompt">$</span>git clone https://github.com/<em>username</em>/<em>username</em>.github.io</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li id="setup-in-desktop" class="option-desktop image-right">
|
||||||
|
<h4>Clone the repository</h4>
|
||||||
|
<p>Click the "Set up in Desktop" button. When the GitHub desktop app opens, save the project.</p>
|
||||||
|
|
||||||
|
<p class="details">If the app doesn't open, launch it and clone the repository from the app.</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li id="setup-in-desktop" class="option-newuser image-right">
|
||||||
|
<h4>Clone the repository</h4>
|
||||||
|
<p>After finishing the installation, head back to GitHub.com and refresh the page. Click the "Set up in Desktop" button. When the GitHub desktop app opens, save the project.</p>
|
||||||
|
|
||||||
|
<p class="details">If the app doesn't open, launch it and clone the repository from the app.</p>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-terminal">
|
||||||
|
<h4>Hello World</h4>
|
||||||
|
<p>Enter the project folder and add an index.html file:</p>
|
||||||
|
|
||||||
|
<div class="terminal">
|
||||||
|
<div class="header"></div>
|
||||||
|
<div class="shell">
|
||||||
|
<p><span class="path">~</span><span class="prompt">$</span>cd <em>username</em>.github.io</p>
|
||||||
|
<p><span class="path">~</span><span class="prompt">$</span>echo "Hello World" > index.html</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-desktop option-newuser">
|
||||||
|
<h4>Create an index file</h4>
|
||||||
|
<p>Grab your favorite text editor and add an index.html file to your project:</p>
|
||||||
|
|
||||||
|
<div class="terminal">
|
||||||
|
<div class="header">index.html</div>
|
||||||
|
<code class="shell">
|
||||||
|
<pre><!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>Hello World</h1>
|
||||||
|
<p>I'm hosted with GitHub Pages.</p>
|
||||||
|
</body>
|
||||||
|
</html></pre>
|
||||||
|
</code>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-terminal">
|
||||||
|
<h4>Push it</h4>
|
||||||
|
<p>Add, commit, and push your changes:</p>
|
||||||
|
|
||||||
|
<div class="terminal">
|
||||||
|
<div class="header"></div>
|
||||||
|
<div class="shell">
|
||||||
|
<p><span class="path">~</span><span class="prompt">$</span>git add --all</p>
|
||||||
|
<p><span class="path">~</span><span class="prompt">$</span>git commit -m "Initial commit"</p>
|
||||||
|
<p><span class="path">~</span><span class="prompt">$</span>git push -u origin main</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-desktop option-newuser">
|
||||||
|
<h4>Commit & publish</h4>
|
||||||
|
|
||||||
|
<p>Enter the repository, commit your changes, and press the publish button.</p>
|
||||||
|
|
||||||
|
<img src="https://pages.github.com/images/desktop-demo@2x.gif" width="841" alt="Demonstration of steps required to create the initial commit and publish the repository in GitHub Desktop" class="macos-drop-shadow" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-all">
|
||||||
|
<h4>…and you're done!</h4>
|
||||||
|
<p>Fire up a browser and go to <strong>https://<em>username</em>.github.io</strong>.</p>
|
||||||
|
<div class="hero-octicon">
|
||||||
|
<span class="mega-octicon octicon-check"></span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<!-- End of user site tutorial -->
|
||||||
|
|
||||||
|
<!-- Project Site tutorial -->
|
||||||
|
<ul id="project-site" class="tutorial-list wrapper">
|
||||||
|
<li class="question">
|
||||||
|
<h4>Use a theme, or start from scratch?</h4>
|
||||||
|
<p>You have the option to start with one of the pre-built themes,
|
||||||
|
<br>or to create a site from scratch.
|
||||||
|
<ul class="tabs">
|
||||||
|
<li><a id="option-generate" href="#generate-step-1" class="selected">Choose a theme</a></li>
|
||||||
|
<li><a id="option-vanilla" href="#vanilla-step-1">Start from scratch</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li id="generate-step-1" class="option-generate">
|
||||||
|
<h4>Repository Settings</h4>
|
||||||
|
<p>Head over to <a href="https://github.com/">GitHub.com</a> and create a new repository, or go to an existing one.
|
||||||
|
<br><strong>Click on the Settings tab</strong>.</p>
|
||||||
|
|
||||||
|
<img src="https://pages.github.com/images/repo-settings@2x.png" width="720" alt="Settings for a repository" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-generate">
|
||||||
|
<h4>Theme chooser</h4>
|
||||||
|
<p>Scroll down to the <strong>GitHub Pages</strong> section. Press <strong>Choose a theme</strong>.</p>
|
||||||
|
<img src="https://pages.github.com/images/launch-theme-chooser@2x.png" width="720" alt="Automatic Generator button on GitHub.com, Settings" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-generate">
|
||||||
|
<h4>Pick a theme</h4>
|
||||||
|
<p>Choose one of the themes from the carousel at the top.
|
||||||
|
<br>When you're done, click <strong>Select theme</strong> on the right.</p>
|
||||||
|
|
||||||
|
<img src="https://pages.github.com/images/theme-chooser@2x.png" class="full-size" width="720" alt="Choose layout" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-generate">
|
||||||
|
<h4>Edit content</h4>
|
||||||
|
<p>Use the editor to add content to your site.</p>
|
||||||
|
<img class="full-size" src="https://pages.github.com/images/code-editor@2x.png" width="720" alt="Add content to your GitHub Pages site" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-generate">
|
||||||
|
<h4>Commit</h4>
|
||||||
|
<p>Enter a commit comment and click on <strong>Commit changes</strong> below the editor.</p>
|
||||||
|
<img class="full-size" src="https://pages.github.com/images/commit-edits@2x.png" width="720" alt="Commit Markdown content to your repository" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<!-- Start of vanilla sub tutorial -->
|
||||||
|
<li id="vanilla-step-1" class="option-vanilla">
|
||||||
|
<h4>Create an index file</h4>
|
||||||
|
<p>Head over to <a href="https://github.com/">GitHub.com</a> and <a data-proofer-ignore="true" href="https://github.com/new">create a new repository</a>, or go to an existing one.
|
||||||
|
<br />Click on the <strong>Create new file</strong> button.</p>
|
||||||
|
|
||||||
|
<img src="https://pages.github.com/images/new-create-file@2x.png" width="720" alt="Create a file in your repository" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-vanilla">
|
||||||
|
<h4>Hello World</h4>
|
||||||
|
<p>Name the file <code>index.html</code> and type some HTML content into the editor.</p>
|
||||||
|
|
||||||
|
<img src="https://pages.github.com/images/new-index-html@2x.png" width="720" alt="Hello World on GitHub.com" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-vanilla">
|
||||||
|
<h4>Commit the file</h4>
|
||||||
|
<p>Scroll to the bottom of the page, write a commit message, and commit the new file.</p>
|
||||||
|
|
||||||
|
<img src="https://pages.github.com/images/new-commit-file@2x.png" width="720" alt="Commit the file" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-vanilla">
|
||||||
|
<h4>Repository Settings</h4>
|
||||||
|
<p><strong>Click on the Settings tab</strong> and scroll down to the GitHub Pages section.
|
||||||
|
<br />Then select the <strong>main branch</strong> source and click on the <strong>Save</strong> button.</p>
|
||||||
|
|
||||||
|
<img src="https://pages.github.com/images/source-setting@2x.png" width="720" alt="GitHub Pages Source Setting" />
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="option-all">
|
||||||
|
<h4>…and you're done!</h4>
|
||||||
|
<p>Fire up a browser and go to <strong>http://<em>username</em>.github.io/<em>repository</em></strong>.</p>
|
||||||
|
<div class="hero-octicon">
|
||||||
|
<span class="mega-octicon octicon-check"></span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<!-- End of tutorial section -->
|
||||||
|
|
||||||
|
<section id="next-steps">
|
||||||
|
<h1>Now that you’re up and running, here are a few things you should know.</h1>
|
||||||
|
|
||||||
|
<ul class="next-steps wrapper">
|
||||||
|
<li class="jekyll">
|
||||||
|
<a class="hero-octicon" href="https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll">
|
||||||
|
<span class="mega-octicon octicon-pencil"></span>
|
||||||
|
</a>
|
||||||
|
<h4><a href="https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll">Blogging with Jekyll</a></h4>
|
||||||
|
<p>Using <a href="https://jekyllrb.com">Jekyll</a>, you can blog using beautiful Markdown syntax, and without having to deal with any databases. <a href="https://jekyllrb.com/docs/">Learn how to set up Jekyll</a>.</p>
|
||||||
|
</li>
|
||||||
|
<li class="custom-urls">
|
||||||
|
<a class="hero-octicon" href="https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site">
|
||||||
|
<span class="mega-octicon octicon-link"></span>
|
||||||
|
</a>
|
||||||
|
<h4><a href="https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site">Custom URLs</a></h4>
|
||||||
|
<p>Want to use your own custom domain for a GitHub Pages site? Just create a file named CNAME and include your URL. <a href="https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site">Read more</a>.</p>
|
||||||
|
</li>
|
||||||
|
<li class="guides">
|
||||||
|
<a class="hero-octicon" href="https://docs.github.com/pages">
|
||||||
|
<span class="mega-octicon octicon-book"></span>
|
||||||
|
</a>
|
||||||
|
<h4><a href="https://docs.github.com/pages">Guides</a></h4>
|
||||||
|
<p>Learn how to create custom 404 pages, use submodules, and <a href="https://docs.github.com/pages">learn more about GitHub Pages</a>.</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<script src="https://pages.github.com/js/jquery.js"></script>
|
||||||
|
<script>window.slides = {"bootstrap":"Bootstrap","yeoman":"Yeoman","facebookdesign":"Facebook Design","foundation":"Foundation","ghtraining":"GitHub Training","adobeos":"Adobe Open Source","jekyllrb":"Jekyll","electron":"Electron","semanticui":"Semantic UI","microsoft":"Microsoft on GitHub"}</script>
|
||||||
|
<script src="https://pages.github.com/js/application.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class="page-footer">
|
||||||
|
<ul class="site-footer-links right">
|
||||||
|
<li><a href="https://www.githubstatus.com/">Status</a></li>
|
||||||
|
<li><a href="https://docs.github.com/rest">API</a></li>
|
||||||
|
<li><a href="https://training.github.com">Training</a></li>
|
||||||
|
<li><a href="https://shop.github.com">Shop</a></li>
|
||||||
|
<li><a href="https://github.blog">Blog</a></li>
|
||||||
|
<li><a href="https://github.com/about">About</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<a href="/">
|
||||||
|
<span class="mega-octicon octicon-mark-github"></span>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<ul class="site-footer-links">
|
||||||
|
<li>© 2025 <span>GitHub</span>, Inc.</li>
|
||||||
|
<li><a href="https://docs.github.com/en/github/site-policy/github-terms-of-service">Terms</a></li>
|
||||||
|
<li><a href="https://docs.github.com/en/github/site-policy/github-privacy-statement">Privacy</a></li>
|
||||||
|
<li><a href="https://github.com/security">Security</a></li>
|
||||||
|
<li><a href="https://support.github.com">Contact</a></li>
|
||||||
|
</ul>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue