-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathform_app.py
More file actions
130 lines (107 loc) · 4.14 KB
/
Copy pathform_app.py
File metadata and controls
130 lines (107 loc) · 4.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# PDF Style Engine v2.0
# (c) 2025 Claudia Ortega
# Licensed under CC BY-NC-ND 4.0
# https://creativecommons.org/licenses/by-nc-nd/4.0/
"""
form_app.py
===========
Flask web server that serves the interactive PDF form and calls pdf_generator.
Run:
python form_app.py
Then open: http://localhost:5050
"""
import io
import json
import os
import tempfile
import traceback
from flask import Flask, jsonify, render_template_string, request, send_file
# Import the generator from the same directory
import sys
sys.path.insert(0, os.path.dirname(__file__))
from pdf_generator import generate_pdf
app = Flask(__name__)
app.config["MAX_CONTENT_LENGTH"] = 8 * 1024 * 1024 # 8 MB upload limit
# ---------------------------------------------------------------------------
# Read the HTML template from a sibling file
# ---------------------------------------------------------------------------
TEMPLATE_PATH = os.path.join(os.path.dirname(__file__), "form.html")
@app.route("/")
def index():
with open(TEMPLATE_PATH, encoding="utf-8") as f:
return render_template_string(f.read())
# ---------------------------------------------------------------------------
# /generate — POST multipart/form-data
# ---------------------------------------------------------------------------
@app.route("/generate", methods=["POST"])
def generate():
try:
style = request.form.get("style", "professional").strip()
# ---- core fields ----
data = {}
for field in ("title", "subtitle", "date", "reference",
"company", "contact", "ascii_art", "hash_id"):
val = (request.form.get(field) or "").strip()
if val:
data[field] = val
# ---- sections (JSON array sent as string) ----
sections_raw = request.form.get("sections", "[]")
sections = json.loads(sections_raw)
# drop empty entries
sections = [s for s in sections
if (s.get("heading") or "").strip()
or (s.get("body") or "").strip()]
if sections:
data["sections"] = sections
# ---- table ----
table_raw = request.form.get("table", "{}")
table = json.loads(table_raw)
headers = [h for h in table.get("headers", []) if str(h).strip()]
rows = [
[str(c) for c in row]
for row in table.get("rows", [])
if any(str(c).strip() for c in row)
]
if headers and rows:
data["table"] = {"headers": headers, "rows": rows}
# ---- logo upload (professional only) ----
logo_file = request.files.get("logo")
logo_tmp = None
if logo_file and logo_file.filename:
suffix = os.path.splitext(logo_file.filename)[-1].lower()
if suffix in (".png", ".jpg", ".jpeg"):
logo_tmp = tempfile.NamedTemporaryFile(
suffix=suffix, delete=False
)
logo_file.save(logo_tmp.name)
data["logo_path"] = logo_tmp.name
# ---- generate into a temp file, stream back ----
out_tmp = tempfile.NamedTemporaryFile(suffix=".pdf", delete=False)
out_tmp.close()
generate_pdf(style, data, out_tmp.name)
# Build a friendly filename
safe_title = "".join(
c if c.isalnum() or c in "-_ " else "_"
for c in data.get("title", "document")
).strip().replace(" ", "_")[:40]
filename = f"{safe_title}_{style}.pdf"
with open(out_tmp.name, "rb") as f:
pdf_bytes = f.read()
# Clean up temp files
os.unlink(out_tmp.name)
if logo_tmp:
os.unlink(logo_tmp.name)
return send_file(
io.BytesIO(pdf_bytes),
mimetype="application/pdf",
as_attachment=True,
download_name=filename,
)
except Exception:
tb = traceback.format_exc()
return jsonify({"error": tb}), 500
if __name__ == "__main__":
print("\n PDF Form Studio")
print(" ───────────────")
print(" Open in browser → http://localhost:5050\n")
app.run(port=5050, debug=False)