106 lines
2.9 KiB
Python
106 lines
2.9 KiB
Python
"""Export service for VoIdea — JSON, Markdown, HTML (printable as PDF)."""
|
|
|
|
import json
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
|
|
def export_json(
|
|
title: str,
|
|
content: str,
|
|
metadata: dict[str, Any] | None = None,
|
|
) -> str:
|
|
data = {
|
|
"title": title,
|
|
"exported_at": datetime.utcnow().isoformat(),
|
|
"content": content,
|
|
"metadata": metadata or {},
|
|
}
|
|
return json.dumps(data, ensure_ascii=False, indent=2)
|
|
|
|
|
|
def export_markdown(
|
|
title: str,
|
|
content: str,
|
|
metadata: dict[str, Any] | None = None,
|
|
) -> str:
|
|
lines = [f"# {title}", ""]
|
|
if metadata:
|
|
for k, v in metadata.items():
|
|
lines.append(f"- **{k}**: {v}")
|
|
lines.append("")
|
|
lines.append("---")
|
|
lines.append("")
|
|
lines.append(content)
|
|
lines.append("")
|
|
lines.append(f"*Экспортировано {datetime.utcnow().isoformat()}*")
|
|
return "\n".join(lines)
|
|
|
|
|
|
def export_html(
|
|
title: str,
|
|
content: str,
|
|
metadata: dict[str, Any] | None = None,
|
|
) -> str:
|
|
meta_rows = ""
|
|
if metadata:
|
|
for k, v in metadata.items():
|
|
meta_rows += f"<tr><td><strong>{k}</strong></td><td>{v}</td></tr>\n"
|
|
|
|
content_html = content.replace("\n", "<br>\n")
|
|
return f"""<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>{title}</title>
|
|
<style>
|
|
body {{ font-family: 'Segoe UI', sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; color: #333; }}
|
|
h1 {{ color: #1a1a2e; border-bottom: 2px solid #e0e0e0; padding-bottom: 10px; }}
|
|
table {{ width: 100%; border-collapse: collapse; margin: 20px 0; }}
|
|
td {{ padding: 6px 12px; border: 1px solid #e0e0e0; }}
|
|
.meta {{ background: #f5f5f5; border-radius: 8px; padding: 16px; margin: 20px 0; }}
|
|
.footer {{ margin-top: 40px; font-size: 12px; color: #999; text-align: center; }}
|
|
@media print {{ body {{ margin: 0; }} }}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>{title}</h1>
|
|
<div class="meta"><table>{meta_rows}</table></div>
|
|
<hr>
|
|
<div>{content_html}</div>
|
|
<div class="footer">Экспортировано из VoIdeaAI • {datetime.utcnow().isoformat()}</div>
|
|
</body>
|
|
</html>"""
|
|
|
|
|
|
CONTENT_TYPE_MAP = {
|
|
"json": "application/json",
|
|
"md": "text/markdown; charset=utf-8",
|
|
"html": "text/html; charset=utf-8",
|
|
}
|
|
|
|
FILE_EXT_MAP = {
|
|
"json": "json",
|
|
"md": "md",
|
|
"html": "html",
|
|
}
|
|
|
|
|
|
def export_content(
|
|
fmt: str,
|
|
title: str,
|
|
content: str,
|
|
metadata: dict[str, Any] | None = None,
|
|
) -> tuple[str, str, str]:
|
|
"""Export content in requested format.
|
|
|
|
Returns (content_str, content_type, file_extension).
|
|
"""
|
|
fmt = fmt.lower()
|
|
if fmt == "json":
|
|
return export_json(title, content, metadata), CONTENT_TYPE_MAP["json"], FILE_EXT_MAP["json"]
|
|
elif fmt == "md":
|
|
return export_markdown(title, content, metadata), CONTENT_TYPE_MAP["md"], FILE_EXT_MAP["md"]
|
|
else:
|
|
return export_html(title, content, metadata), CONTENT_TYPE_MAP["html"], FILE_EXT_MAP["html"]
|